Commit f1473eb4 authored by Jacek Furmankiewicz's avatar Jacek Furmankiewicz

restarting fine-grained security work

parent 1d20fc0e
......@@ -3,12 +3,29 @@ Enhancements to core Twisted security
@author: jacekf
'''
from twisted.cred.checkers import ICredentialsChecker, FilePasswordDB
from twisted.cred.checkers import ICredentialsChecker
from zope.interface import implements
from beaker.cache import CacheManager
from beaker.util import parse_cache_config_options
class Principal:
'''A security principal with privileges attached to it'''
def __init__(self,userId,privileges=None):
'''
@param userId -- mandatory user ID
@param privileges -- list of privileges assigned to this user
'''
self.__userId = userId
self.__privileges = privileges
@property
def userId(self):
return self.__userId
@property
def privileges(self):
return self.__privileges
class CachedCredentialsChecker:
"""A cached credentials checker wrapper. It will forward calls to the actual credentials checker only when the cache expires (or on first call)"""
......@@ -17,33 +34,28 @@ class CachedCredentialsChecker:
def __init__(self,credentialInterfaces,credentialsChecker):
self.credentialInterfaces = credentialInterfaces
self.checker = credentialsChecker
#initialize cache
cacheOptions = {
'cache.type': 'memory',
}
self.cache = CacheManager(**parse_cache_config_options(cacheOptions))
def requestAvatarId(self,credentials):
pass
class SqlCredentialsChecker:
"""A SQL checked to compare usernames and passwords to a DB table, with support for custom comparison (plaintext, hash, etc)"""
implements(ICredentialsChecker)
def __init__(self,dbpool,userTable,usernameColumn,passwordColumn,passwordChecker = None):
"""Constructor
@param dbpool: adbapi DB connection pool
@param userTable: Name of the table containing list of users
@param userameColumn: Name of column containing the user name
@param passwordColumn: Name of column containing the user password (or its hash)
@param passwordChecker: A lambda that compares the incoming password due what is stored in DB (plaintext comparison (not recommended, insecure), hash, decryption, etc.)
"""
self.dbpool = dbpool
self.userTable = userTable
self.usernameColumn = usernameColumn
self.passwordColumn = passwordColumn
self.passwordChecker = passwordChecker
##################################################################################################
#
# DECORATORS
#
##################################################################################################
def requestAvatarId(self,credentials):
pass
def secured(privileges=None):
'''
Main decorator for securing REST endpoints via roles
'''
pass
......
'''
Stand-alone security module with support for role-based authorization and IP address range checking
@author: jacekf
'''
#from IPy import IP
class SecurityRole:
'''Represents a security role'''
def __init__(self,roleId,ipRanges=None):
'''
roleId -- role roleId
ipRanges -- list of ipRanges in any of the formats accepted by the IPy library
'''
self.__roleId = roleId
self.__ipRanges = ipRanges
@property
def roleId(self):
return self.__roleId
class Principal:
'''An enhanced Avatar with roles & IP Address ranges attached to it'''
def __init__(self,userId,roles=None,ipRanges=None):
'''
userId -- mandatory user ID
roles -- list of optional SecurityRole instances
ipRanges - user-specific IP ranges (checked before the role ones)
'''
self.__userId = userId
self.__roles = roles
self.__ipRanges = ipRanges
@property
def userId(self):
return self.__userId
def validateAccess(self,expectedRoles,ipAddress):
'''
Validates if the current Principal has access to any of the expected roles, coming from the current request IP address
'''
pass
class SqlCredentialsFactory:
'''A default credentials factory configured to obtain credentials / roles / IP address ranges via custom SQL queries'''
def __init__(self,
dbConnectionPool,userQuery="SELECT USER_ID FROM USER",
userIpRangeQuery = "SELECT IP_RANGE FROM USER_IP_RANGE WHERE USER_ID = :userId",
roleQuery="SELECT R.ROLE_ID FROM USER_ROLE UR, ROLE R WHERE UR.USER_ID = :userId AND UR.ROLE_PK = R.ROLE_PK",
roleIpRangeQuery="SELECT IP_RANGE FROM ROLE_IP_RANGE WHERE ROLE_ID = :roleId"):
'''
Constructor that allows passing custom SQL queries to get the desired info. Override with your custom queries to fit your data model:
userQuery -- SQL query to retrieve list of users. Should return just the user ID column
userIpRangeQuery -- query to get IP ranges associated with user. Pass in None to disable this functionality
roleQuery -- query to get list of roles for user. Pass in None to disable this functionality
roleIpRangeQuery - query to get IP range string column associated with a particular role. Pass in None to disable this functionality
'''
pass
##################################################################################################
#
# DECORATORS
#
##################################################################################################
def secure(roles=None):
'''
Main decorator for securing REST endpoints via roles
'''
pass
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment