예제 #1
0
    def test_principals_allowed_by_permission_no_acls(self):
        from pyramid.authorization import ACLHelper

        helper = ACLHelper()
        context = DummyContext()
        result = sorted(
            helper.principals_allowed_by_permission(context, 'read'))
        self.assertEqual(result, [])
예제 #2
0
    def test_callable_acl(self):
        from pyramid.authorization import ACLHelper, Allow

        helper = ACLHelper()
        context = DummyContext()
        fn = lambda self: [(Allow, 'bob', 'read')]
        context.__acl__ = fn.__get__(context, context.__class__)
        result = helper.permits(context, ['bob'], 'read')
        self.assertTrue(result)
예제 #3
0
    def test_principals_allowed_by_permission_deny_permission_in_acl(self):
        from pyramid.authorization import ACLHelper, Deny, Everyone

        helper = ACLHelper()
        context = DummyContext()
        acl = [(Deny, Everyone, 'read')]
        context.__acl__ = acl
        result = sorted(
            helper.principals_allowed_by_permission(context, 'read'))
        self.assertEqual(result, [])
예제 #4
0
    def test_principals_allowed_by_permission_string_permission(self):
        from pyramid.authorization import ACLHelper, Allow

        helper = ACLHelper()
        context = DummyContext()
        acl = [(Allow, 'chrism', 'read_it')]
        context.__acl__ = acl
        result = helper.principals_allowed_by_permission(context, 'read')
        # would be ['chrism'] if 'read' were compared against 'read_it' instead
        # of against ['read_it']
        self.assertEqual(list(result), [])
예제 #5
0
    def test_string_permissions_in_acl(self):
        from pyramid.authorization import ACLHelper, Allow

        helper = ACLHelper()
        root = DummyContext()
        root.__acl__ = [(Allow, 'wilma', 'view_stuff')]

        result = helper.permits(root, ['wilma'], 'view')
        # would be True if matching against 'view_stuff' instead of against
        # ['view_stuff']
        self.assertEqual(result, False)
예제 #6
0
    def test_no_acl(self):
        from pyramid.authorization import ACLHelper

        context = DummyContext()
        helper = ACLHelper()
        result = helper.permits(context, ['foo'], 'permission')
        self.assertEqual(result, False)
        self.assertEqual(result.ace, '<default deny>')
        self.assertEqual(result.acl,
                         '<No ACL found on any object in resource lineage>')
        self.assertEqual(result.permission, 'permission')
        self.assertEqual(result.principals, ['foo'])
        self.assertEqual(result.context, context)
예제 #7
0
    def test_principals_allowed_by_permission_callable_acl(self):
        from pyramid.authorization import DENY_ALL, ACLHelper, Allow

        helper = ACLHelper()
        context = DummyContext()
        acl = lambda: [
            (Allow, 'chrism', ('read', 'write')),
            DENY_ALL,
            (Allow, 'other', 'read'),
        ]
        context.__acl__ = acl
        result = sorted(
            helper.principals_allowed_by_permission(context, 'read'))
        self.assertEqual(result, ['chrism'])
예제 #8
0
class MySecurityPolicy:
    def __init__(self, secret):
        self.authtkt = AuthTktCookieHelper(secret)
        self.acl = ACLHelper()

    def identity(self, request):
        identity = self.authtkt.identify(request)
        if identity is not None and identity['userid'] in USERS:
            return identity

    def authenticated_userid(self, request):
        identity = self.identity(request)
        if identity is not None:
            return identity['userid']

    def remember(self, request, userid, **kw):
        return self.authtkt.remember(request, userid, **kw)

    def forget(self, request, **kw):
        return self.authtkt.forget(request, **kw)

    def permits(self, request, context, permission):
        principals = self.effective_principals(request)
        return self.acl.permits(context, principals, permission)

    def effective_principals(self, request):
        principals = [Everyone]
        identity = self.identity(request)
        if identity is not None:
            principals.append(Authenticated)
            principals.append('u:' + identity['userid'])
            principals.extend(GROUPS.get(identity['userid'], []))
        return principals
예제 #9
0
 def permits(self, request, context, permission):
     # use the identity to build a list of principals, and pass them
     # to the ACLHelper to determine allowed/denied
     identity = request.identity
     principals = set([Everyone])
     if identity is not None:
         principals.add(Authenticated)
         principals.add(identity['userid'])
         principals.update(identity['principals'])
     return ACLHelper().permits(context, principals, permission)
예제 #10
0
    def test_principals_allowed_by_permission(self):
        from pyramid.authorization import ACLHelper
        from pyramid.security import Allow
        from pyramid.security import Deny
        from pyramid.security import DENY_ALL
        from pyramid.security import ALL_PERMISSIONS

        helper = ACLHelper()
        root = DummyContext(__name__='', __parent__=None)
        community = DummyContext(__name__='community', __parent__=root)
        blog = DummyContext(__name__='blog', __parent__=community)
        root.__acl__ = [
            (Allow, 'chrism', ('read', 'write')),
            (Allow, 'other', ('read', )),
            (Allow, 'jim', ALL_PERMISSIONS),
        ]
        community.__acl__ = [
            (Deny, 'flooz', 'read'),
            (Allow, 'flooz', 'read'),
            (Allow, 'mork', 'read'),
            (Deny, 'jim', 'read'),
            (Allow, 'someguy', 'manage'),
        ]
        blog.__acl__ = [(Allow, 'fred', 'read'), DENY_ALL]

        result = sorted(helper.principals_allowed_by_permission(blog, 'read'))
        self.assertEqual(result, ['fred'])
        result = sorted(
            helper.principals_allowed_by_permission(community, 'read'))
        self.assertEqual(result, ['chrism', 'mork', 'other'])
        result = sorted(
            helper.principals_allowed_by_permission(community, 'read'))
        result = sorted(helper.principals_allowed_by_permission(root, 'read'))
        self.assertEqual(result, ['chrism', 'jim', 'other'])
예제 #11
0
class MySecurityPolicy:
    def __init__(self, secret):
        self.authtkt = AuthTktCookieHelper(secret)
        self.identity_cache = RequestLocalCache(self.load_identity)
        self.acl = ACLHelper()

    def load_identity(self, request):
        identity = self.authtkt.identify(request)
        if identity is None:
            return None

        userid = identity['userid']
        user = request.dbsession.query(models.User).get(userid)
        return user

    def identity(self, request):
        return self.identity_cache.get_or_create(request)

    def authenticated_userid(self, request):
        user = self.identity(request)
        if user is not None:
            return user.id

    def remember(self, request, userid, **kw):
        return self.authtkt.remember(request, userid, **kw)

    def forget(self, request, **kw):
        return self.authtkt.forget(request, **kw)

    def permits(self, request, context, permission):
        principals = self.effective_principals(request)
        return self.acl.permits(context, principals, permission)

    def effective_principals(self, request):
        principals = [Everyone]
        user = self.identity(request)
        if user is not None:
            principals.append(Authenticated)
            principals.append('u:' + str(user.id))
            principals.append('role:' + user.role)
        return principals
예제 #12
0
 def __init__(self, secret):
     self.authtkt = AuthTktCookieHelper(secret)
     self.acl = ACLHelper()
예제 #13
0
 def __init__(self, secret):
     self.authtkt = AuthTktCookieHelper(secret)
     self.identity_cache = RequestLocalCache(self.load_identity)
     self.acl = ACLHelper()
예제 #14
0
    def test_acl(self):
        from pyramid.authorization import ACLHelper
        from pyramid.security import Deny
        from pyramid.security import Allow
        from pyramid.security import Everyone
        from pyramid.security import Authenticated
        from pyramid.security import ALL_PERMISSIONS
        from pyramid.security import DENY_ALL

        helper = ACLHelper()
        root = DummyContext()
        community = DummyContext(__name__='community', __parent__=root)
        blog = DummyContext(__name__='blog', __parent__=community)
        root.__acl__ = [(Allow, Authenticated, VIEW)]
        community.__acl__ = [
            (Allow, 'fred', ALL_PERMISSIONS),
            (Allow, 'wilma', VIEW),
            DENY_ALL,
        ]
        blog.__acl__ = [
            (Allow, 'barney', MEMBER_PERMS),
            (Allow, 'wilma', VIEW),
        ]

        result = helper.permits(blog, [Everyone, Authenticated, 'wilma'],
                                'view')
        self.assertEqual(result, True)
        self.assertEqual(result.context, blog)
        self.assertEqual(result.ace, (Allow, 'wilma', VIEW))
        self.assertEqual(result.acl, blog.__acl__)

        result = helper.permits(blog, [Everyone, Authenticated, 'wilma'],
                                'delete')
        self.assertEqual(result, False)
        self.assertEqual(result.context, community)
        self.assertEqual(result.ace, (Deny, Everyone, ALL_PERMISSIONS))
        self.assertEqual(result.acl, community.__acl__)

        result = helper.permits(blog, [Everyone, Authenticated, 'fred'],
                                'view')
        self.assertEqual(result, True)
        self.assertEqual(result.context, community)
        self.assertEqual(result.ace, (Allow, 'fred', ALL_PERMISSIONS))
        result = helper.permits(blog, [Everyone, Authenticated, 'fred'],
                                'doesntevenexistyet')
        self.assertEqual(result, True)
        self.assertEqual(result.context, community)
        self.assertEqual(result.ace, (Allow, 'fred', ALL_PERMISSIONS))
        self.assertEqual(result.acl, community.__acl__)

        result = helper.permits(blog, [Everyone, Authenticated, 'barney'],
                                'view')
        self.assertEqual(result, True)
        self.assertEqual(result.context, blog)
        self.assertEqual(result.ace, (Allow, 'barney', MEMBER_PERMS))
        result = helper.permits(blog, [Everyone, Authenticated, 'barney'],
                                'administer')
        self.assertEqual(result, False)
        self.assertEqual(result.context, community)
        self.assertEqual(result.ace, (Deny, Everyone, ALL_PERMISSIONS))
        self.assertEqual(result.acl, community.__acl__)

        result = helper.permits(root, [Everyone, Authenticated, 'someguy'],
                                'view')
        self.assertEqual(result, True)
        self.assertEqual(result.context, root)
        self.assertEqual(result.ace, (Allow, Authenticated, VIEW))
        result = helper.permits(blog, [Everyone, Authenticated, 'someguy'],
                                'view')
        self.assertEqual(result, False)
        self.assertEqual(result.context, community)
        self.assertEqual(result.ace, (Deny, Everyone, ALL_PERMISSIONS))
        self.assertEqual(result.acl, community.__acl__)

        result = helper.permits(root, [Everyone], 'view')
        self.assertEqual(result, False)
        self.assertEqual(result.context, root)
        self.assertEqual(result.ace, '<default deny>')
        self.assertEqual(result.acl, root.__acl__)

        context = DummyContext()
        result = helper.permits(context, [Everyone], 'view')
        self.assertEqual(result, False)
        self.assertEqual(result.ace, '<default deny>')
        self.assertEqual(result.acl,
                         '<No ACL found on any object in resource lineage>')
예제 #15
0
 def __init__(self, comp, options):
     self.comp = comp
     self.options = options
     self.test_user = None
     self.acl_helper = ACLHelper()
예제 #16
0
class SecurityPolicy(object):
    def __init__(self, comp, options):
        self.comp = comp
        self.options = options
        self.test_user = None
        self.acl_helper = ACLHelper()

    @property
    def oauth(self):
        return self.comp.oauth

    def identity(self, request):
        # Override current user in tests via ngw_auth_administrator fixture
        if self.test_user is not None:
            return User.by_keyname(self.test_user).id

        session = request.session

        # Session based authentication

        current = session.get('auth.policy.current')
        if current is not None:
            atype, user_id, exp = current[0:3]
            exp = datetime.fromtimestamp(int(exp))

            now = datetime.utcnow()
            expired = exp <= now

            if atype == 'OAUTH':
                if len(current) != 3:
                    raise ValueError("Invalid OAuth session data")

                if expired:
                    try:
                        tresp = self.oauth.grant_type_refresh_token(
                            refresh_token=session['auth.policy.refresh_token'],
                            access_token=session['auth.policy.access_token'])
                        self.remember(request, (user_id, tresp))
                    except OAuthTokenRefreshException:
                        self.forget(request)
                        return None

                return user_id

            elif atype == 'LOCAL':
                if expired:
                    return None

                refresh, = current[3:]
                if datetime.fromtimestamp(refresh) <= now:
                    session['auth.policy.current'] = current[0:2] + (
                        int((now +
                             self.options['local.lifetime']).timestamp()),
                        int((now + self.options['local.refresh']).timestamp()),
                    )

                return user_id

            else:
                raise ValueError("Invalid authentication type: " + atype)

        # HTTP based authentication

        ahead = request.headers.get('Authorization')
        if ahead is not None:
            try:
                amode, value = ahead.split(' ', maxsplit=1)
            except ValueError:
                raise InvalidAuthorizationHeader()
            amode = amode.upper()

            if amode == 'BASIC':
                try:
                    decoded = b64decode(value).decode('utf-8')
                    username, password = decoded.split(':', maxsplit=1)
                except ValueError:
                    raise InvalidAuthorizationHeader()

                # Allow token authorization via basic when
                # username is empty (for legacy clients).

                if username == '':
                    amode = 'BEARER'
                    value = password

                else:
                    user, _ = self.authenticate_with_password(
                        username, password)
                    return user.id

            if amode == 'BEARER' and self.oauth is not None:
                user = self.oauth.access_token_to_user(value)
                if user is not None:
                    return user.id

            raise HTTPUnauthorized()

        return None

    def authenticated_userid(self, request):
        return self.identity(request)

    def permits(self, request, context, permission):
        return self.acl_helper.permits(context, [], permission)

    def remember(self, request, what, **kw):
        session = request.session
        user_id, tresp = what
        if user_id is None:
            raise ValueError("Empty user_id in a session")

        atype = 'LOCAL' if tresp is None else 'OAUTH'
        exp = int((datetime.utcnow() + self.options['local.lifetime']).timestamp()) \
            if tresp is None else tresp.expires

        session['auth.policy.current'] = (atype, user_id, int(exp)) + ((int(
            (datetime.utcnow() + self.options['local.refresh']
             ).timestamp()), ) if atype == 'LOCAL' else ())

        for k in ('access_token', 'refresh_token'):
            sk = 'auth.policy.{}'.format(k)
            if tresp is None:
                if sk in session:
                    del session[sk]
            else:
                session[sk] = getattr(tresp, k)

        return ()

    def forget(self, request, **kw):
        session = request.session

        for k in ('current', 'access_token', 'refresh_token'):
            sk = 'auth.policy.{}'.format(k)
            if sk in session:
                del session[sk]

        if session.get('invite'):

            def forget_session(request, response):
                cookie_name = request.env.pyramid.options[
                    'session.cookie.name']
                cs = WebSession.cookie_settings(request)
                response.delete_cookie(cookie_name,
                                       path=cs['path'],
                                       domain=cs['domain'])

            request.add_response_callback(forget_session)

        return ()

    def authenticate_with_password(self, username, password):
        user = None
        tresp = None

        # Step 1: Authentication with local credentials

        q = User.filter(sa.func.lower(User.keyname) == username.lower())
        if self.oauth and not self.oauth.local_auth:
            q = q.filter_by(oauth_subject=None)

        try:
            test_user = q.one()
            if test_user.disabled:
                raise UserDisabledException()
            elif test_user.password == password:
                user = test_user
        except NoResultFound:
            pass

        # Step 2: Authentication with OAuth password if enabled

        if user is None and self.oauth is not None and self.oauth.password:
            try:
                tresp = self.oauth.grant_type_password(username, password)
            except OAuthPasswordGrantTypeException:
                pass
            else:
                user = self.oauth.access_token_to_user(tresp.access_token)

        if user is None:
            raise InvalidCredentialsException()

        return (user, tresp)

    option_annotations = OptionAnnotations(
        (Option('local.lifetime',
                timedelta,
                default=timedelta(days=1),
                doc="Local authentication lifetime."),
         Option('local.refresh',
                timedelta,
                default=timedelta(hours=1),
                doc="Refresh local authentication lifetime interval.")))