mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Introducing basic session security - REQUIRES DATABASE SCHEMA CHANGE and REQUIRES CONFIG CHANGE.
SQL commands for schema changes: ALTER TABLE galaxy_session ADD COLUMN current_history_id INTEGER; ALTER TABLE galaxy_session ADD FOREIGN KEY (current_history_id) REFERENCES history(id); ALTER TABLE galaxy_session ADD COLUMN session_key VARCHAR(255) UNIQUE; ALTER TABLE galaxy_session ADD COLUMN is_valid BOOLEAN DEFAULT false; ALTER TABLE galaxy_session ADD COLUMN prev_session_id INTEGER; Galaxy config change: In the [app:main] section, add: # Galaxy session security id_secret = changethisinproductiontoo 1) The "universe", "universe_user" and "universe_session" cookies are deprecated and replaced with 1 new cookie named galaxysession". The deprecated cookies are still supported and will be for at least 90 days, but when a valid one is found, the value is taken and used to create a new "galaxysession" cookie and the deprecated cookie is immediately expired. 2) The value of the new "galaxysession" cookie is an encrypted unique, high entropy 128 bit random number. The decoded value is the value stored in the new session_key column of the galaxy_session table. 3) Whenever a user logs in or out they get a new GalaxySession, and the old one in the database is marked as invalidated, so a compromised cookie won't survive across login/logout. Also, when creating the new session, a reference to the previous one is saved ( via the new prev_session_id column in the galaxy_session table ) so we have a way to chain them together.
This commit is contained in:
@@ -14,6 +14,9 @@ import tempfile
|
||||
import galaxy.datatypes.registry
|
||||
from galaxy.datatypes.metadata import MetadataCollection
|
||||
|
||||
import logging
|
||||
log = logging.getLogger( __name__ )
|
||||
|
||||
datatypes_registry = galaxy.datatypes.registry.Registry() #Default Value Required for unit tests
|
||||
|
||||
def set_datatypes_registry( d_registry ):
|
||||
@@ -121,9 +124,12 @@ class History( object ):
|
||||
last_hid = dataset.hid
|
||||
return last_hid + 1
|
||||
|
||||
def add_galaxy_session( self, galaxy_session ):
|
||||
self.galaxy_sessions.append( GalaxySessionToHistoryAssociation( galaxy_session, self ) )
|
||||
|
||||
def add_galaxy_session( self, galaxy_session, association=None ):
|
||||
if association is None:
|
||||
self.galaxy_sessions.append( GalaxySessionToHistoryAssociation( galaxy_session, self ) )
|
||||
else:
|
||||
self.galaxy_sessions.append( association )
|
||||
|
||||
def add_dataset( self, dataset, parent_id=None, genome_build=None, set_hid = True ):
|
||||
if parent_id:
|
||||
for data in self.datasets:
|
||||
@@ -487,16 +493,23 @@ class Event( object ):
|
||||
self.message = message
|
||||
|
||||
class GalaxySession( object ):
|
||||
def __init__( self, id=None, user=None, remote_host=None, remote_addr=None, referer=None ):
|
||||
def __init__( self, id=None, user=None, remote_host=None, remote_addr=None, referer=None, current_history_id=None, session_key=None, is_valid=False, prev_session_id=None ):
|
||||
self.id = id
|
||||
self.user = user
|
||||
self.remote_host = remote_host
|
||||
self.remote_addr = remote_addr
|
||||
self.referer = referer
|
||||
self.current_history_id = current_history_id
|
||||
self.session_key = session_key
|
||||
self.is_valid = is_valid
|
||||
self.prev_session_id = prev_session_id
|
||||
self.histories = []
|
||||
|
||||
def add_history( self, history ):
|
||||
self.histories.append( GalaxySessionToHistoryAssociation( self, history ) )
|
||||
def add_history( self, history, association=None ):
|
||||
if association is None:
|
||||
self.histories.append( GalaxySessionToHistoryAssociation( self, history ) )
|
||||
else:
|
||||
self.histories.append( association )
|
||||
|
||||
class GalaxySessionToHistoryAssociation( object ):
|
||||
def __init__( self, galaxy_session, history ):
|
||||
|
||||
@@ -173,7 +173,12 @@ GalaxySession.table = Table( "galaxy_session", metadata,
|
||||
Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True, nullable=True ),
|
||||
Column( "remote_host", String( 255 ) ),
|
||||
Column( "remote_addr", String( 255 ) ),
|
||||
Column( "referer", TEXT ) )
|
||||
Column( "referer", TEXT ),
|
||||
Column( "current_history_id", Integer, ForeignKey( "history.id" ), nullable=True ),
|
||||
Column( "session_key", TrimmedString( 255 ), index=True, unique=True ), # unique 128 bit random number coerced to a string
|
||||
Column( "is_valid", Boolean, default=False ),
|
||||
Column( "prev_session_id", Integer ) # saves a reference to the previous session so we have a way to chain them together
|
||||
)
|
||||
|
||||
GalaxySessionToHistoryAssociation.table = Table( "galaxy_session_to_history", metadata,
|
||||
Column( "id", Integer, primary_key=True ),
|
||||
|
||||
@@ -411,7 +411,6 @@ class RootController( BaseController ):
|
||||
new_history = history.copy()
|
||||
new_history.name = history.name+" from "+user.email
|
||||
new_history.user_id = send_to_user.id
|
||||
new_history.add_galaxy_session(trans.get_galaxy_session( create=True ))
|
||||
trans.log_event( "History share, id: %s, name: '%s': to new id: %s" % (str(history.id), history.name, str(new_history.id)) )
|
||||
self.app.model.flush()
|
||||
return trans.show_message( "History (%s) has been shared with: %s" % (",".join(history_names),email) )
|
||||
@@ -449,7 +448,12 @@ class RootController( BaseController ):
|
||||
new_history = import_history.copy()
|
||||
new_history.name = "imported: "+new_history.name
|
||||
new_history.user_id = user.id
|
||||
new_history.add_galaxy_session(trans.get_galaxy_session( create=True ))
|
||||
galaxy_session = trans.get_galaxy_session()
|
||||
try:
|
||||
association = trans.app.model.GalaxySessionToHistoryAssociation.selectone_by( session_id=galaxy_session.id, history_id=new_history.id )
|
||||
except:
|
||||
association = None
|
||||
new_history.add_galaxy_session( galaxy_session, association=association )
|
||||
new_history.flush()
|
||||
if not user_history.datasets:
|
||||
trans.set_history( new_history )
|
||||
@@ -461,7 +465,12 @@ class RootController( BaseController ):
|
||||
new_history = import_history.copy()
|
||||
new_history.name = "imported: "+new_history.name
|
||||
new_history.user_id = None
|
||||
new_history.add_galaxy_session(trans.get_galaxy_session( create=True ))
|
||||
galaxy_session = trans.get_galaxy_session()
|
||||
try:
|
||||
association = trans.app.model.GalaxySessionToHistoryAssociation.selectone_by( session_id=galaxy_session.id, history_id=new_history.id )
|
||||
except:
|
||||
association = None
|
||||
new_history.add_galaxy_session( galaxy_session, association=association )
|
||||
new_history.flush()
|
||||
trans.set_history( new_history )
|
||||
trans.log_event( "History imported, id: %s, name: '%s': " % (str(new_history.id) , new_history.name ) )
|
||||
@@ -481,7 +490,12 @@ class RootController( BaseController ):
|
||||
else:
|
||||
new_history = trans.app.model.History.get( id )
|
||||
if new_history:
|
||||
new_history.add_galaxy_session(trans.get_galaxy_session( create=True ))
|
||||
galaxy_session = trans.get_galaxy_session()
|
||||
try:
|
||||
association = trans.app.model.GalaxySessionToHistoryAssociation.selectone_by( session_id=galaxy_session.id, history_id=new_history.id )
|
||||
except:
|
||||
association = None
|
||||
new_history.add_galaxy_session( galaxy_session, association=association )
|
||||
new_history.flush()
|
||||
trans.set_history( new_history )
|
||||
trans.log_event( "History switched to id: %s, name: '%s'" % (str(new_history.id), new_history.name ) )
|
||||
|
||||
@@ -90,15 +90,11 @@ class User( BaseController ):
|
||||
.add_text( "email", "Email address", value=email, error=email_error )
|
||||
.add_password( "password", "Password", value='', error=password_error,
|
||||
help="<a href='%s'>Forgot password? Reset here</a>" % web.url_for( action='reset_password' ) ) )
|
||||
|
||||
@web.expose
|
||||
def logout( self, trans ):
|
||||
# Since logging an event requires a session, we'll log prior to ending the session
|
||||
trans.log_event( "User logged out" )
|
||||
# If the current history is saved for the current user it should be disconnected.
|
||||
if trans.history.user == trans.user:
|
||||
trans.set_history( None )
|
||||
trans.set_user( None )
|
||||
trans.end_galaxy_session()
|
||||
new_galaxy_session = trans.logout_galaxy_session()
|
||||
return trans.show_ok_message( "You are no longer logged in", refresh_frames=['masthead', 'history'] )
|
||||
|
||||
@web.expose
|
||||
|
||||
@@ -108,7 +108,6 @@ class UniverseWebTransaction( base.DefaultWebTransaction ):
|
||||
# that the current history should not be used for parameter values
|
||||
# and such).
|
||||
self.workflow_building_mode = False
|
||||
|
||||
@property
|
||||
def sa_session( self ):
|
||||
"""
|
||||
@@ -117,7 +116,6 @@ class UniverseWebTransaction( base.DefaultWebTransaction ):
|
||||
to allow migration toward a more SQLAlchemy 0.4 style of use.
|
||||
"""
|
||||
return self.app.model.context.current
|
||||
|
||||
def log_event( self, message, tool_id=None, **kwargs ):
|
||||
"""
|
||||
Application level logging. Still needs fleshing out (log levels and
|
||||
@@ -138,119 +136,196 @@ class UniverseWebTransaction( base.DefaultWebTransaction ):
|
||||
self.ensure_valid_galaxy_session()
|
||||
event.session_id = self.galaxy_session.id
|
||||
event.flush()
|
||||
|
||||
def get_cookie( self, name='universe' ):
|
||||
"""
|
||||
Convienience method for getting the universe cookie
|
||||
"""
|
||||
def get_cookie( self, name='galaxysession' ):
|
||||
"""Convienience method for getting the galaxysession cookie"""
|
||||
try:
|
||||
# If we've changed the cookie during the request return the new
|
||||
# value
|
||||
# If we've changed the cookie during the request return the new value
|
||||
if name in self.response.cookies:
|
||||
return self.response.cookies[name].value
|
||||
else:
|
||||
return self.request.cookies[name].value
|
||||
except Exception:
|
||||
except:
|
||||
return None
|
||||
|
||||
def set_cookie( self, value, name='universe', path='/', age=90, version='1' ):
|
||||
"""
|
||||
Convienience method for setting the universe cookie
|
||||
"""
|
||||
def set_cookie( self, value, name='galaxysession', path='/', age=90, version='1' ):
|
||||
"""Convienience method for setting the galaxysession cookie"""
|
||||
# The galaxysession cookie value must be a high entropy 128 bit random number encrypted
|
||||
# using a server secret key. Any other value is invalid and could pose security issues.
|
||||
self.response.cookies[name] = value
|
||||
self.response.cookies[name]['path'] = path
|
||||
self.response.cookies[name]['max-age'] = 3600 * 24 * age
|
||||
tstamp = time.localtime ( time.time() + 3600 * 24 * age )
|
||||
self.response.cookies[name]['expires'] = time.strftime('%a, %d-%b-%Y %H:%M:%S GMT', tstamp)
|
||||
self.response.cookies[name]['path'] = path
|
||||
self.response.cookies[name]['max-age'] = 3600 * 24 * age # 90 days
|
||||
tstamp = time.localtime ( time.time() + 3600 * 24 * age )
|
||||
self.response.cookies[name]['expires'] = time.strftime( '%a, %d-%b-%Y %H:%M:%S GMT', tstamp )
|
||||
self.response.cookies[name]['version'] = version
|
||||
|
||||
def get_history( self, create=False ):
|
||||
"""
|
||||
Load the current history
|
||||
"""
|
||||
"""Load the current history"""
|
||||
if self.__history is NOT_SET:
|
||||
history = None
|
||||
id = self.get_cookie( name='universe' )
|
||||
if id:
|
||||
history = self.app.model.History.get( id )
|
||||
if history is None or history.deleted:
|
||||
history = self.new_history()
|
||||
self.__history = history
|
||||
if create is True and ( history is None or history.deleted ):
|
||||
history = self.new_history()
|
||||
return self.__history
|
||||
|
||||
self.__history = None
|
||||
# See if we have a galaxysession cookie
|
||||
secure_id = self.get_cookie( name='galaxysession' )
|
||||
if secure_id:
|
||||
session_key = self.security.decode_session_key( secure_id )
|
||||
try:
|
||||
galaxy_session = self.app.model.GalaxySession.selectone_by( session_key=session_key )
|
||||
if galaxy_session and galaxy_session.is_valid and galaxy_session.current_history_id:
|
||||
history = self.app.model.History.get( galaxy_session.current_history_id )
|
||||
if history and not history.deleted:
|
||||
self.__history = history
|
||||
except Exception, e:
|
||||
# This should only occur in development if the cookie is not synced with the db
|
||||
pass
|
||||
else:
|
||||
# See if we have a deprecated universe cookie
|
||||
# TODO: this should be eliminated some time after October 1, 2008
|
||||
# We'll keep it until then because the old universe cookies are valid for 90 days
|
||||
history_id = self.get_cookie( name='universe' )
|
||||
if history_id:
|
||||
history = self.app.model.History.get( int( history_id ) )
|
||||
if history and not history.deleted:
|
||||
self.__history = history
|
||||
# Expire the universe cookie since it is deprecated
|
||||
self.set_cookie( name='universe', value=id, age=0 )
|
||||
if self.__history is None:
|
||||
return self.new_history()
|
||||
if create is True and self.__history is None:
|
||||
return self.new_history()
|
||||
return self.__history
|
||||
def new_history( self ):
|
||||
history = self.app.model.History()
|
||||
"""
|
||||
We are associating the last used genome_build with histories, so we will always
|
||||
initialize a new history with the first dbkey in util.dbnames which is currently
|
||||
? unspecified (?)
|
||||
"""
|
||||
history.genome_build = util.dbnames.default_value
|
||||
if history.user_id is None and self.user is not None:
|
||||
history.user_id = self.user.id
|
||||
if self.galaxy_session_is_valid():
|
||||
history.add_galaxy_session(self.get_galaxy_session())
|
||||
# Make sure we have an id
|
||||
history.flush()
|
||||
self.set_cookie( name='universe', value=history.id )
|
||||
# Immediately associate the new history with self
|
||||
self.__history = history
|
||||
return history
|
||||
|
||||
def set_history( self, history ):
|
||||
if history is None or history.deleted:
|
||||
self.set_cookie( name='universe', value='' )
|
||||
# Make sure we have a valid session to associate with the new history
|
||||
if self.galaxy_session_is_valid():
|
||||
galaxy_session = self.get_galaxy_session()
|
||||
else:
|
||||
self.set_cookie( name='universe', value=history.id )
|
||||
galaxy_session = self.new_galaxy_session()
|
||||
# We are associating the last used genome_build with histories, so we will always
|
||||
# initialize a new history with the first dbkey in util.dbnames which is currently
|
||||
# ? unspecified (?)
|
||||
history.genome_build = util.dbnames.default_value
|
||||
if self.user:
|
||||
history.user_id = self.user.id
|
||||
galaxy_session.user_id = self.user.id
|
||||
try:
|
||||
# See if we have already associated the history with the session
|
||||
association = self.app.model.GalaxySessionToHistoryAssociation.select_by( session_id=galaxy_session.id, history_id=history.id )[0]
|
||||
except:
|
||||
association = None
|
||||
history.add_galaxy_session( galaxy_session, association=association )
|
||||
history.flush()
|
||||
galaxy_session.current_history_id = history.id
|
||||
galaxy_session.flush()
|
||||
self.__history = history
|
||||
return self.__history
|
||||
def set_history( self, history ):
|
||||
if history and not history.deleted and self.galaxy_session_is_valid():
|
||||
galaxy_session = self.get_galaxy_session()
|
||||
galaxy_session.current_history_id = history.id
|
||||
galaxy_session.flush()
|
||||
self.__history = history
|
||||
history = property( get_history, set_history )
|
||||
|
||||
def get_user( self ):
|
||||
"""
|
||||
Return the current user if logged in (based on cookie) or `None`.
|
||||
"""
|
||||
"""Return the current user if logged in or None."""
|
||||
if self.__user is NOT_SET:
|
||||
id = self.get_cookie( name='universe_user' )
|
||||
if not id:
|
||||
self.__user = None
|
||||
self.__user = None
|
||||
# See if we have a galaxysession cookie
|
||||
secure_id = self.get_cookie( name='galaxysession' )
|
||||
if secure_id:
|
||||
session_key = self.security.decode_session_key( secure_id )
|
||||
try:
|
||||
galaxy_session = self.app.model.GalaxySession.selectone_by( session_key=session_key )
|
||||
if galaxy_session and galaxy_session.is_valid and galaxy_session.user_id:
|
||||
user = self.app.model.User.get( galaxy_session.user_id )
|
||||
if user:
|
||||
self.__user = user
|
||||
except:
|
||||
# This should only occur in development if the cookie is not synced with the db
|
||||
pass
|
||||
else:
|
||||
self.__user = self.app.model.User.get( int( id ) )
|
||||
# See if we have a deprecated universe_user cookie
|
||||
# TODO: this should be eliminated some time after October 1, 2008
|
||||
# We'll keep it until then because the old universe cookies are valid for 90 days
|
||||
user_id = self.get_cookie( name='universe_user' )
|
||||
if user_id:
|
||||
user = self.app.model.User.get( int( user_id ) )
|
||||
if user:
|
||||
self.__user = user
|
||||
# Expire the universe_user cookie since it is deprecated
|
||||
self.set_cookie( name='universe_user', value='', age=0 )
|
||||
return self.__user
|
||||
|
||||
def set_user( self, user ):
|
||||
"""
|
||||
Set the current user to `user` (by setting a cookie).
|
||||
"""
|
||||
if user is None:
|
||||
self.set_cookie( name='universe_user', value='' )
|
||||
else:
|
||||
self.set_cookie( name='universe_user', value=user.id )
|
||||
"""Set the current user if logged in."""
|
||||
if user is not None and self.galaxy_session_is_valid():
|
||||
galaxy_session = self.get_galaxy_session()
|
||||
if galaxy_session.user_id != user.id:
|
||||
galaxy_session.user_id = user.id
|
||||
galaxy_session.flush()
|
||||
self.__user = user
|
||||
user = property( get_user, set_user )
|
||||
|
||||
def get_galaxy_session( self, create=False ):
|
||||
# Return the current user's galaxy_session.
|
||||
"""Return the current user's GalaxySession"""
|
||||
if self.__galaxy_session is NOT_SET:
|
||||
id = self.get_cookie( name='universe_session' )
|
||||
if not id:
|
||||
self.__galaxy_session = None
|
||||
self.__galaxy_session = None
|
||||
# See if we have a galaxysession cookie
|
||||
secure_id = self.get_cookie( name='galaxysession' )
|
||||
if secure_id:
|
||||
# Decode the cookie value to get the session_key
|
||||
session_key = self.security.decode_session_key( secure_id )
|
||||
try:
|
||||
# Retrive the galaxy_session id via the unique session_key
|
||||
galaxy_session = self.app.model.GalaxySession.selectone_by( session_key=session_key )
|
||||
if galaxy_session and galaxy_session.is_valid:
|
||||
self.__galaxy_session = galaxy_session
|
||||
except:
|
||||
# This should only occur in development if the cookie is not synced with the db
|
||||
pass
|
||||
else:
|
||||
self.__galaxy_session = self.app.model.GalaxySession.get( int( id ) )
|
||||
# See if we have a deprecated universe_session cookie
|
||||
# TODO: this should be eliminated some time after October 1, 2008
|
||||
# We'll keep it until then because the old universe cookies are valid for 90 days
|
||||
session_id = self.get_cookie( name='universe_session' )
|
||||
if session_id:
|
||||
galaxy_session = self.app.model.GalaxySession.get( int( session_id ) )
|
||||
# NOTE: We can't test for is_valid here since the old session records did not include this flag
|
||||
if galaxy_session:
|
||||
# Set the new galaxysession cookie value, old session records did not have a session_key or is_valid flag
|
||||
session_key = self.security.get_new_session_key()
|
||||
galaxy_session.session_key = session_key
|
||||
galaxy_session.is_valid = True
|
||||
galaxy_session.flush()
|
||||
secure_id = self.security.encode_session_key( session_key )
|
||||
self.set_cookie( name='galaxysession', value=secure_id )
|
||||
# Expire the universe_user cookie since it is deprecated
|
||||
self.set_cookie( name='universe_session', value='', age=0 )
|
||||
self.__galaxy_session = galaxy_session
|
||||
if create is True and self.__galaxy_session is None:
|
||||
galaxy_session = self.new_galaxy_session()
|
||||
return self.new_galaxy_session()
|
||||
return self.__galaxy_session
|
||||
|
||||
def new_galaxy_session( self ):
|
||||
# Create a new galaxy_session, retrieving the user's most recently updated history
|
||||
galaxy_session = self.app.model.GalaxySession()
|
||||
if self.user is not None:
|
||||
def new_galaxy_session( self, prev_session_id=None ):
|
||||
"""Create a new secure galaxy_session"""
|
||||
session_key = self.security.get_new_session_key()
|
||||
galaxy_session = self.app.model.GalaxySession( session_key=session_key, is_valid=True, prev_session_id=prev_session_id )
|
||||
# Make sure we have an id
|
||||
galaxy_session.flush()
|
||||
# Immediately associate the new session with self
|
||||
self.__galaxy_session = galaxy_session
|
||||
if prev_session_id is not None:
|
||||
# User logged out, so we need to create a new history for this session
|
||||
self.history = self.new_history()
|
||||
galaxy_session.current_history_id = self.history.id
|
||||
elif self.user is not None:
|
||||
galaxy_session.user_id = self.user.id
|
||||
# Set this session's current_history_id to the user's last updated history
|
||||
h = self.app.model.History
|
||||
ht = h.table
|
||||
where = ( ht.c.user_id==self.user.id ) & ( ht.c.deleted=='f' )
|
||||
history = h.query().filter( where ).order_by( desc( ht.c.update_time ) ).first()
|
||||
if history is not None:
|
||||
if history:
|
||||
self.history = history
|
||||
galaxy_session.current_history_id = self.history.id
|
||||
elif self.history:
|
||||
galaxy_session.current_history_id = self.history.id
|
||||
galaxy_session.remote_host = self.request.remote_host
|
||||
galaxy_session.remote_addr = self.request.remote_addr
|
||||
try:
|
||||
@@ -258,53 +333,60 @@ class UniverseWebTransaction( base.DefaultWebTransaction ):
|
||||
except:
|
||||
galaxy_session.referer = None
|
||||
if self.history is not None:
|
||||
galaxy_session.add_history(self.history)
|
||||
# See if we have already associated the session with the history
|
||||
try:
|
||||
association = self.app.model.GalaxySessionToHistoryAssociation.select_by( session_id=galaxy_session.id, history_id=self.history.id )[0]
|
||||
except:
|
||||
association = None
|
||||
galaxy_session.add_history( self.history, association=association )
|
||||
galaxy_session.flush()
|
||||
self.set_cookie( name='universe_session', value=galaxy_session.id )
|
||||
# Set the cookie value to the encrypted session_key
|
||||
self.set_cookie( name='galaxysession', value=self.security.encode_session_key( session_key ) )
|
||||
self.__galaxy_session = galaxy_session
|
||||
return self.__galaxy_session
|
||||
|
||||
def set_galaxy_session( self, galaxy_session ):
|
||||
# Set the current galaxy_session by setting the universe_session cookie.
|
||||
if galaxy_session is None:
|
||||
#TODO we may want to raise an exception here instead of creating a new galaxy_session
|
||||
galaxy_session = self.new_galaxy_session()
|
||||
else:
|
||||
if galaxy_session.user_id is None and self.user is not None:
|
||||
galaxy_session.user_id = self.user.id
|
||||
galaxy_session.flush()
|
||||
self.set_cookie( name='universe_session', value=galaxy_session.id )
|
||||
self.__galaxy_session = galaxy_session
|
||||
|
||||
def galaxy_session_is_valid( self ):
|
||||
# TODO do we want better validation here?
|
||||
valid = False
|
||||
galaxy_session = self.get_galaxy_session()
|
||||
if galaxy_session is not None and galaxy_session.id is not None:
|
||||
valid = True
|
||||
return valid
|
||||
|
||||
def ensure_valid_galaxy_session( self ):
|
||||
if not self.galaxy_session_is_valid():
|
||||
self.new_galaxy_session()
|
||||
|
||||
def end_galaxy_session( self ):
|
||||
# End the current galaxy_session by expiring the universe_session cookie.
|
||||
if self.galaxy_session_is_valid():
|
||||
self.set_cookie( name='universe_session', value=self.galaxy_session.id, age=0 )
|
||||
self.__galaxy_session = None
|
||||
"""Set the current galaxy_session"""
|
||||
self.__galaxy_session = galaxy_session
|
||||
galaxy_session = property( get_galaxy_session, set_galaxy_session )
|
||||
|
||||
def make_associations( self ):
|
||||
def galaxy_session_is_valid( self ):
|
||||
try:
|
||||
return self.galaxy_session.is_valid
|
||||
except:
|
||||
return False
|
||||
def ensure_valid_galaxy_session( self ):
|
||||
"""Make sure we have a valid galaxy session, create a new one if necessary."""
|
||||
if not self.galaxy_session_is_valid():
|
||||
galaxy_session = self.new_galaxy_session()
|
||||
def logout_galaxy_session( self ):
|
||||
"""
|
||||
Logout the current user by setting user to None and galaxy_session.is_valid to False
|
||||
in the db. A new galaxy_session is automatically created with prev_session_id is set
|
||||
to save a reference to the current one as a way of chaining them together
|
||||
"""
|
||||
if self.galaxy_session_is_valid():
|
||||
if self.galaxy_session.user_id is None and self.user is not None:
|
||||
self.galaxy_session.user_id = self.user.id
|
||||
self.galaxy_session.flush()
|
||||
self.__galaxy_session = self.galaxy_session
|
||||
if self.history is not None and self.user is not None:
|
||||
self.history.user_id = self.user.id
|
||||
self.history.flush()
|
||||
self.__history = self.history
|
||||
galaxy_session = self.get_galaxy_session()
|
||||
old_session_id = galaxy_session.id
|
||||
galaxy_session.is_valid = False
|
||||
galaxy_session.flush()
|
||||
self.set_user( None )
|
||||
return self.new_galaxy_session( prev_session_id=old_session_id )
|
||||
else:
|
||||
error( "Attempted to logout an invalid galaxy_session" )
|
||||
def make_associations( self ):
|
||||
history = self.get_history()
|
||||
user = self.get_user()
|
||||
if self.galaxy_session_is_valid():
|
||||
galaxy_session = self.get_galaxy_session()
|
||||
if galaxy_session.user_id is None and user is not None:
|
||||
galaxy_session.user_id = user.id
|
||||
if history is not None:
|
||||
galaxy_session.current_history_id = history.id
|
||||
galaxy_session.flush()
|
||||
self.__galaxy_session = galaxy_session
|
||||
if history is not None and user is not None:
|
||||
history.user_id = user.id
|
||||
history.flush()
|
||||
self.__history = history
|
||||
|
||||
def get_toolbox(self):
|
||||
"""Returns the application toolbox"""
|
||||
|
||||
@@ -2,11 +2,15 @@ import pkg_resources
|
||||
pkg_resources.require( "pycrypto" )
|
||||
|
||||
from Crypto.Cipher import Blowfish
|
||||
from Crypto.Util.randpool import RandomPool
|
||||
from Crypto.Util import number
|
||||
|
||||
class SecurityHelper( object ):
|
||||
# TODO: checking if histories/datasets are owned by the current user) will be moved here.
|
||||
def __init__( self, **config ):
|
||||
self.id_secret = config['id_secret']
|
||||
self.id_cipher = Blowfish.new( self.id_secret )
|
||||
self.__random_pool = RandomPool( 1024 )
|
||||
def encode_id( self, id ):
|
||||
# Convert to string
|
||||
s = str( id )
|
||||
@@ -15,4 +19,22 @@ class SecurityHelper( object ):
|
||||
# Encrypt
|
||||
return self.id_cipher.encrypt( s ).encode( 'hex' )
|
||||
def decode_id( self, id ):
|
||||
return int( self.id_cipher.decrypt( id.decode( 'hex' ) ).lstrip( "!" ) )
|
||||
return int( self.id_cipher.decrypt( id.decode( 'hex' ) ).lstrip( "!" ) )
|
||||
def encode_session_key( self, session_key ):
|
||||
# Session keys are strings
|
||||
# Pad to a multiple of 8 with leading "!"
|
||||
s = ( "!" * ( 8 - len( session_key ) % 8 ) ) + session_key
|
||||
# Encrypt
|
||||
return self.id_cipher.encrypt( s ).encode( 'hex' )
|
||||
def decode_session_key( self, session_key ):
|
||||
# Session keys are strings
|
||||
return self.id_cipher.decrypt( session_key.decode( 'hex' ) ).lstrip( "!" )
|
||||
def get_new_session_key( self ):
|
||||
# Generate a unique, high entropy 128 bit random number
|
||||
while self.__random_pool.entropy < 100:
|
||||
self.__random_pool.add_event()
|
||||
self.__random_pool.stir()
|
||||
rn = number.getRandomNumber( 128, self.__random_pool.get_bytes )
|
||||
# session_key must be a string
|
||||
return str( rn )
|
||||
|
||||
@@ -61,6 +61,9 @@ session_data_dir = %(here)s/database/beaker_sessions
|
||||
session_key = galaxysessions
|
||||
session_secret = changethisinproduction
|
||||
|
||||
# Galaxy session security
|
||||
id_secret = changethisinproductiontoo
|
||||
|
||||
# Configuration for debugging middleware
|
||||
debug = true
|
||||
use_lint = false
|
||||
|
||||
Reference in New Issue
Block a user