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
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)
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)
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)
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
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>')
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.")))