Forked from
DM / dm-docs
261 commits behind, 149 commits ahead of the upstream repository.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
sessionManager.py 8.48 KiB
#!/usr/bin/env python
import urllib
import urllib2
import urlparse
import time
import getpass
import os
import stat
import ssl
import types
from dm.common.constants import dmServiceConstants
from dm.common.exceptions.configurationError import ConfigurationError
from dm.common.exceptions.authorizationError import AuthorizationError
from dm.common.exceptions.urlError import UrlError
from dm.common.utility.loggingManager import LoggingManager
from dm.common.utility.configurationManager import ConfigurationManager
from dm.common.utility.osUtility import OsUtility
from dm.common.client.dmExceptionMapper import DmExceptionMapper
from dm.common.client.dmHttpsHandler import DmHttpsHandler
class SessionManager:
""" Class for session management. """
def __init__(self):
self.sessionCookie = None
self.host = None
self.logger = LoggingManager.getInstance().getLogger(self.__class__.__name__)
self.username = ''
self.password = ''
self.urlOpener = None
cm = ConfigurationManager.getInstance()
self.sessionCacheFile = cm.getSessionCacheFile()
self.requireSessionCredentials = cm.getRequireSessionCredentials()
def setHost(self, host):
self.host = host
def hasSession(self):
""" Return true if we have session established. """
if self.sessionCookie is not None:
return True
return False
def establishSession(self, url, username, password, selector='/dm/login'):
self.host = url
self.username = username
self.password = password
self.sessionCookie = self.loadSession()
if self.sessionCookie is not None:
return
# Could not load session.
try:
# User will be asked for username/password if they are not
# provided.
data = { 'username' : self.getUsername(username), 'password' : self.getPassword(password) }
self.logger.debug('Establishing session for user %s @ %s)' % (username, url))
(response,responseData) = self.sendRequest(url='%s%s' % (url, selector), method='POST', contentType='application/x-www-form-urlencoded', data=urllib.urlencode(data))
except urllib2.URLError, ex:
self.logger.exception('%s' % ex)
raise UrlError(exception=ex)
#self.logger.debug('Got headers: %s' % response.headers)
# This will save session cookie.
self.sessionCookie = self.checkResponseHeadersForErrorsAndSaveSession(response.headers)
self.logger.debug('User %s session cookie: %s' % (username, self.sessionCookie))
def getUsername(self, username):
if username is None and self.requireSessionCredentials:
return self.askForUsername()
return username
def askForUsername(self):
defaultUsername = getpass.getuser()
username = raw_input('Username [%s]: ' % defaultUsername)
username = username.strip()
if not len(username):
username = defaultUsername
return username
def getPassword(self, password):
if password is None and self.requireSessionCredentials:
return self.askForPassword()
return password
def askForPassword(self):
password = getpass.getpass()
password = password.strip()
if not len(password):
raise AuthorizationError('Empty password provided.')
return password
def clearSessionFile(self):
if self.sessionCacheFile is None:
return
try:
self.logger.debug('Clearing session cache: %s' % (self.sessionCacheFile))
OsUtility.removeFile(self.sessionCacheFile)
except Exception, ex:
# ignore errors.
self.logger.warn('Could not clear session cache: %s' % (ex))
pass
def saveSession(self, sessionCookie):
if self.sessionCacheFile is None:
return
if sessionCookie is None:
return
try:
f = open(self.sessionCacheFile, 'w')
f.write('%s' % sessionCookie)
f.close()
os.chmod(self.sessionCacheFile, stat.S_IRUSR|stat.S_IWUSR|stat.S_IXUSR)
except Exception, ex:
self.logger.warn('Could not save session: %s' % (ex))
def loadSession(self):
if self.sessionCacheFile is None:
return None
try:
f = open(self.sessionCacheFile, 'r')
session = f.read()
expires = session.split(';')[1].split('=')[-1]
t = time.mktime(time.strptime(expires, '%a, %d %b %Y %H:%M:%S %Z'))
now = time.time()
if t < now:
return None
else:
self.logger.debug('Loaded session from %s: %s' % (self.sessionCacheFile, session))
return session
except Exception, ex:
self.logger.warn('Could not load session: %s' % (ex))
return None
def getUrlOpener(self, protocol):
if not self.urlOpener:
if protocol == dmServiceConstants.DM_SERVICE_PROTOCOL_HTTPS:
# HTTPS, use custom https handler, which
# should work even if any of cert/key/cacert files is None
cm = ConfigurationManager.getInstance()
keyFile = cm.getSslKeyFile()
certFile = cm.getSslCertFile()
self.urlOpener = urllib2.build_opener(DmHttpsHandler)
#self.logger.debug('Using Dm HTTPS Handler')
else:
# HTTP, use standard http handler
self.urlOpener = urllib2.build_opener(urllib2.HTTPHandler)
# Install opener before returning it.
urllib2.install_opener(self.urlOpener)
return self.urlOpener
def sendRequest(self, url, method, contentType='html', data={}):
""" Send http request without cookies. """
if url.find('://') < 0:
url = '%s%s' % (self.host, url)
parsedUrl = urlparse.urlparse(url)
protocol = parsedUrl[0]
path = parsedUrl[2]
self.logger.debug('Sending request: %s' % url)
encodedData = ''
if data is not None:
if type(data) == types.DictType and len(data):
encodedData=urllib.urlencode(data)
contentType='application/x-www-form-urlencoded'
elif type(data) == types.StringType:
encodedData = data
request = urllib2.Request(url, data=encodedData)
request.get_method = lambda: method
request.add_header('Content-Type', contentType)
request.add_header('Content-Length', str(len(data)))
if self.sessionCookie != None:
request.add_header('Cookie', self.sessionCookie)
try:
opener = self.getUrlOpener(protocol)
response = opener.open(request)
except urllib2.HTTPError, ex:
# If we see dm headers, dm exception will be thrown,
# otherwise we'll throw UrlError
self.checkResponseHeadersForErrors(ex.hdrs)
self.logger.exception('%s' % ex)
raise UrlError(exception=ex)
except urllib2.URLError, ex:
self.logger.exception('%s' % ex)
raise UrlError(exception=ex)
# Check headers for errors and update session cookie
sessionCookie = self.checkResponseHeadersForErrorsAndSaveSession(response.headers)
if sessionCookie != None:
self.sessionCookie = sessionCookie
responseData = response.read()
return (response, responseData)
def sendSessionRequest(self, url, method, contentType='html', data={}):
""" Send session request. """
if self.sessionCookie is None:
self.establishSession(self.host, self.username, self.password)
return self.sendRequest(url, method, contentType, data)
def checkResponseHeadersForErrorsAndSaveSession(self, responseHeaders):
try:
DmExceptionMapper.checkStatus(responseHeaders)
sessionCookie = responseHeaders.get('Set-Cookie')
self.saveSession(sessionCookie)
return sessionCookie
except AuthorizationError, ex:
self.clearSessionFile()
raise
def checkResponseHeadersForErrors(self, responseHeaders):
try:
DmExceptionMapper.checkStatus(responseHeaders)
except AuthorizationError, ex:
self.clearSessionFile()
raise
#######################################################################
# Testing.
if __name__ == '__main__':
sm = SessionManager.createSession()