Changeset 6888
- Timestamp:
- 24/05/10 15:01:36 (11 years ago)
- Location:
- TI12-security/trunk/MyProxyServerUtils
- Files:
-
- 1 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
TI12-security/trunk/MyProxyServerUtils/.pydevproject
r6886 r6888 8 8 <pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.6</pydev_property> 9 9 <pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Python2.6</pydev_property> 10 <pydev_pathproperty name="org.python.pydev.PROJECT_EXTERNAL_SOURCE_PATH"> 11 <path>/home/pjkersha/workspace/MyProxyClient</path> 12 </pydev_pathproperty> 10 13 </pydev_project> -
TI12-security/trunk/MyProxyServerUtils/myproxy/__init__.py
r6881 r6888 1 """MyProxy Server Utilities myproxy namespace package 2 3 This is a setuptools namespace_package. DO NOT place any other 4 code in this file! There is no guarantee that it will be installed 5 with easy_install. See: 6 7 http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages 8 9 ... for details. 10 """ 11 __author__ = "P J Kershaw" 12 __date__ = "21/05/10" 13 __copyright__ = "(C) 2010 Science and Technology Facilities Council" 14 __license__ = "BSD - see LICENSE file in top-level directory" 15 __contact__ = "Philip.Kershaw@stfc.ac.uk" 16 __revision__ = '$Id$' 17 18 __import__('pkg_resources').declare_namespace(__name__) -
TI12-security/trunk/MyProxyServerUtils/myproxy/server/test/myproxywsgi.ini
r6887 r6888 1 1 # 2 # SSL Client Authn WSGI Testing environment configuration 2 # MyProxy Logon Application in file for unit tests. 3 # 4 # Author: P J Kershaw 5 # 6 # Date: 21/05/10 7 # 8 # Copyright: STFC 2010 9 # 10 # Licence: BSD - See top-level LICENCE file for licence details 3 11 # 4 12 # The %(here)s variable will be replaced with the parent directory of this file 5 13 # 6 [DEFAULT]7 testConfigDir = %(here)s/../../../config8 9 14 [server:main] 10 15 use = egg:Paste#http … … 12 17 port = 5000 13 18 14 [pipeline:main] 15 pipeline = SSLClientAuthnFilter TestApp 16 17 [app:TestApp] 18 paste.app_factory = ndg.security.test.unit.wsgi.ssl.test_ssl:TestSSLClientAuthnApp 19 20 [filter:SSLClientAuthnFilter] 21 paste.filter_app_factory = ndg.security.server.wsgi.ssl:ApacheSSLAuthnMiddleware 22 prefix = ssl. 23 ssl.caCertFilePathList = %(testConfigDir)s/ca/ndg-test-ca.crt 24 ssl.rePathMatchList = ^/secured/.*$ ^/restrict.* 25 ssl.clientCertDNMatchList = /O=NDG/OU=BADC/CN=test, /O=localhost/OU=local client/CN=test 2 19 [app:main] 20 paste.app_factory = myproxy.server.wsgi.app:MyProxyLogonApp.app_factory 21 prefix = myproxy. 22 myproxy.logonFuncEnvKeyName = MYPROXY_LOGON_FUNC 23 myproxy.rePathMatchList = /logon 24 myproxy.client.hostname = localhost 25 myproxy.client.caCertDir = /etc/grid-security/certificates -
TI12-security/trunk/MyProxyServerUtils/myproxy/server/test/test_myproxywsgi.py
r6886 r6888 9 9 __revision__ = '$Id: $' 10 10 import logging 11 logging.basicConfig(level=logging.DEBUG) 11 12 12 13 import unittest 13 14 import os 14 import re 15 import base64 16 from getpass import getpass 17 from ConfigParser import SafeConfigParser, NoOptionError 15 18 19 from OpenSSL import crypto 16 20 import paste.fixture 17 21 from paste.deploy import loadapp 18 22 23 from myproxy.server.wsgi.middleware import MyProxyClientMiddleware 19 24 20 class TestSSLClientAuthnApp(BaseTestCase): 21 '''Test Application for the Authentication handler to protect''' 22 response = "Test Authentication redirect application" 23 24 def __init__(self, app_conf, **local_conf): 25 pass 25 26 class TestMyProxyClientMiddlewareApp(object): 27 '''Test Application for MyClientProxyMiddleware''' 28 RESPONSE = "Test MyProxyClientMiddleware" 26 29 27 30 def __call__(self, environ, start_response): 28 31 29 if environ['PATH_INFO'] == '/secured/uri': 30 status = "200 OK" 31 32 elif environ['PATH_INFO'] == '/unsecured': 33 status = "200 OK" 34 35 elif environ['PATH_INFO'] == '/test_200WithNotLoggedIn': 36 status = "200 OK" 37 38 elif environ['PATH_INFO'] == '/test_200WithLoggedIn': 39 environ['REMOTE_USER'] = 'testuser' 40 status = "200 OK" 41 else: 42 status = "404 Not found" 32 assert(environ[MyProxyClientMiddleware.CLIENT_ENV_KEYNAME]) 33 assert(environ[MyProxyClientMiddleware.LOGON_FUNC_ENV_KEYNAME]) 34 status = "200 OK" 43 35 44 36 start_response(status, 45 37 [('Content-length', 46 str(len( TestSSLClientAuthnApp.response))),38 str(len(self.__class__.RESPONSE))), 47 39 ('Content-type', 'text/plain')]) 48 return [ TestSSLClientAuthnApp.response]40 return [self.__class__.RESPONSE] 49 41 50 42 51 class MyProxyWSGITestCase(BaseTestCase): 43 class MyProxyClientMiddlewareTestCase(unittest.TestCase): 44 def __init__(self, *args, **kwargs): 45 app = TestMyProxyClientMiddlewareApp() 46 app = MyProxyClientMiddleware.filter_app_factory(app, {}, prefix='') 47 self.app = paste.fixture.TestApp(app) 48 49 unittest.TestCase.__init__(self, *args, **kwargs) 52 50 51 def test01AssertMyProxyClientInEnviron(self): 52 # Check the middleware has set the MyProxy client object in environ 53 response = self.app.get('/', status=200) 54 self.assert_(response) 55 56 57 class MyProxyLogonAppTestCase(unittest.TestCase): 58 INI_FILENAME = 'myproxywsgi.ini' 59 THIS_DIR = os.path.dirname(__file__) 60 CONFIG_FILENAME = 'test_myproxywsgi.cfg' 61 CONFIG_FILEPATH = os.path.join(THIS_DIR, CONFIG_FILENAME) 62 53 63 def __init__(self, *args, **kwargs): 54 64 here_dir = os.path.dirname(os.path.abspath(__file__)) 55 wsgiapp = loadapp('config:test.ini', relative_to=here_dir) 65 wsgiapp = loadapp('config:' + MyProxyLogonAppTestCase.INI_FILENAME, 66 relative_to=here_dir) 56 67 self.app = paste.fixture.TestApp(wsgiapp) 57 58 BaseTestCase.__init__(self, *args, **kwargs)59 68 60 61 def test01NotAnSSLRequest(self): 62 # This request should be ignored because the SSL environment settings 63 # are not present 64 response = self.app.get('/unsecured') 65 66 def test02NoClientCertSet(self): 67 extra_environ = {'HTTPS':'1'} 68 response = self.app.get('/secured/uri', 69 extra_environ=extra_environ, 70 status=401) 71 72 def test03ClientCertSet(self): 73 thisDir = os.path.dirname(__file__) 74 sslClientCertFilePath = os.path.join( 75 os.environ[BaseTestCase.configDirEnvVarName], 76 'pki', 77 'test.crt') 78 sslClientCert = X509Cert.Read(sslClientCertFilePath).toString() 79 extra_environ = {'HTTPS':'1', 'SSL_CLIENT_CERT': sslClientCert} 80 response = self.app.get('/secured/uri', 81 extra_environ=extra_environ, 82 status=200) 83 69 self.cfg = SafeConfigParser({'here': MyProxyLogonAppTestCase.THIS_DIR}) 70 self.cfg.optionxform = str 71 self.cfg.read(MyProxyLogonAppTestCase.CONFIG_FILEPATH) 72 73 unittest.TestCase.__init__(self, *args, **kwargs) 74 75 def _createRequestCreds(self): 76 keyPair = crypto.PKey() 77 keyPair.generate_key(crypto.TYPE_RSA, 1024) 78 79 certReq = crypto.X509Req() 80 81 # Create public key object 82 certReq.set_pubkey(keyPair) 83 84 # Add the public key to the request 85 certReq.sign(keyPair, "md5") 86 87 pemCertReq = crypto.dump_certificate_request(crypto.FILETYPE_PEM, 88 certReq) 89 return keyPair, pemCertReq 90 91 def test01Logon(self): 92 username = self.cfg.get('test01Logon', 'username') 93 try: 94 password = self.cfg.get('test01Logon', 'password') 95 except NoOptionError: 96 password = getpass('test01Logon password: ') 97 98 base64String = base64.encodestring('%s:%s' % (username, password))[:-1] 99 authHeader = "Basic %s" % base64String 100 headers = {'Authorization': authHeader} 101 102 # Create key pair and certificate request 103 keyPair, certReq = self._createRequestCreds() 104 response = self.app.post('/logon', certReq, headers=headers, status=200) 105 print response 106 self.assert_(response) 107 84 108 85 109 if __name__ == "__main__": -
TI12-security/trunk/MyProxyServerUtils/myproxy/server/wsgi/app.py
r6886 r6888 9 9 __contact__ = "Philip.Kershaw@stfc.ac.uk" 10 10 __revision__ = "$Id: $" 11 import logging12 log = logging.getLogger(__name__)13 import traceback14 import re15 import httplib16 import socket17 18 11 from myproxy.server.wsgi.httpbasicauth import HttpBasicAuthMiddleware 19 12 from myproxy.server.wsgi.middleware import MyProxyClientMiddleware … … 25 18 26 19 class MyProxyLogonApp(object): 27 """HTTP Basic Auth interface to MyProxy logon. This interfaces creates a 28 MyProxy client instance and HTTP Basic Auth based web service interface 29 for MyProxy logon calls. This WSGI must be run over HTTPS to ensure 30 confidentiality of username/passphrase credentials 20 """HTTP interface to MyProxy logon. This interfaces creates a MyProxy 21 client instance with a HTTP Basic Auth based web service interface 22 to pass username/passphrase for MyProxy logon calls. 23 24 This WSGI must be run over HTTPS to ensure confidentiality of 25 username/passphrase credentials. PKI based verification of requests 26 should be done out of band of this app e.g. in other filter middleware or 27 Apache SSL configuration. 31 28 """ 32 29 PARAM_PREFIX = 'myproxy.logon.' … … 44 41 dictionary 45 42 """ 46 authnFuncEnvKeyNameOptName = HttpBasicAuthMiddleware.PARAM_PREFIX + \ 47 HttpBasicAuthMiddleware.AUTHN_FUNC_ENV_KEYNAME_OPTNAME 48 49 if authnFuncEnvKeyNameOptName in app_conf: 50 raise MyProxyLogonMiddlewareConfigError("Found %r option name in " 51 "application configuration settings. Use %r instead" % 52 (authnFuncEnvKeyNameOptName, 53 MyProxyLogonApp.PARAM_PREFIX + \ 54 MyProxyLogonApp.LOGON_FUNC_ENV_KEYNAME_OPTNAME)) 43 logonFuncEnvKeyNameOptName = prefix + \ 44 MyProxyClientMiddleware.LOGON_FUNC_ENV_KEYNAME_OPTNAME 45 46 logonFuncEnvironKeyName = app_conf.get(logonFuncEnvKeyNameOptName, 47 MyProxyClientMiddleware.LOGON_FUNC_ENV_KEYNAME) 55 48 49 # Mirror callback function setting in HTTP Basic Auth middleware so 50 # that it correctly picks up the authentication function 51 app_conf[prefix + HttpBasicAuthMiddleware.AUTHN_FUNC_ENV_KEYNAME_OPTNAME 52 ] = logonFuncEnvironKeyName 53 56 54 app = MyProxyLogonApp() 57 55 httpBasicAuthMWare = HttpBasicAuthMiddleware.filter_app_factory(app, 58 59 60 56 global_conf, 57 prefix=prefix, 58 **app_conf) 61 59 62 60 app = MyProxyClientMiddleware.filter_app_factory(httpBasicAuthMWare, 63 61 global_conf, 64 prefix ,65 myProxyClientPrefix)62 prefix=prefix, 63 **app_conf) 66 64 67 65 # Set HTTP Basic Auth to use the MyProxy client logon for its 68 66 # authentication method 69 httpBasicAuth App.authnFuncEnvironKeyName = app.logonFuncEnvironKeyName67 httpBasicAuthMWare.authnFuncEnvironKeyName = app.logonFuncEnvironKeyName 70 68 71 69 return app 70 71 def __call__(self, environ, start_response): 72 """Catch case where request path doesn't match mount point for app""" 73 status = response = '404 Not Found' 74 start_response(status, 75 [('Content-type', 'text/plain'), 76 ('Content-length', str(len(response)))]) 77 return [response] 78 72 79 73 80 -
TI12-security/trunk/MyProxyServerUtils/myproxy/server/wsgi/httpbasicauth.py
r6886 r6888 161 161 162 162 creds = base64.decodestring(encodedCreds) 163 username, password = creds. split(HttpBasicAuthMiddleware.FIELD_SEP, 1)163 username, password = creds.rsplit(HttpBasicAuthMiddleware.FIELD_SEP, 1) 164 164 return username, password 165 165 -
TI12-security/trunk/MyProxyServerUtils/myproxy/server/wsgi/middleware.py
r6886 r6888 13 13 log = logging.getLogger(__name__) 14 14 import traceback 15 15 import socket 16 import httplib 17 from cStringIO import StringIO 18 19 from OpenSSL import crypto 16 20 from myproxy.client import MyProxyClient, MyProxyClientError 17 21 … … 31 35 32 36 # Default environ key names 33 CLIENT_ENV_KEYNAME = (' ndg.security.server.wsgi.authn.'34 'MyProxyClientMiddleware ')35 LOGON_FUNC_ENV_KEYNAME = (' ndg.security.server.wsgi.authn.'37 CLIENT_ENV_KEYNAME = ('myproxy.server.wsgi.middleware.' 38 'MyProxyClientMiddleware.myProxyClient') 39 LOGON_FUNC_ENV_KEYNAME = ('myproxy.server.wsgi.middleware.' 36 40 'MyProxyClientMiddleware.logon') 37 41 … … 179 183 """ 180 184 if environ.get('REQUEST_METHOD') == 'POST': 181 pemCertReq = environ[ 182 MyProxyClientMiddleware.WSGI_INPUT_ENV_KEYNAME].read() 183 184 # TODO: restore WSGI file object 185 wsgiInput = environ[ 186 MyProxyClientMiddleware.WSGI_INPUT_ENV_KEYNAME] 187 pemCertReq = wsgiInput.read() 188 189 # Restore WSGI file object with duck typing(!) 190 wsgiInput = StringIO() 191 wsgiInput.write(pemCertReq) 192 wsgiInput.seek(0) 185 193 186 194 # Expecting PEM encoded request 187 certReq = X509.load_request_string(pemCertReq) 195 certReq = crypto.load_certificate_request( 196 crypto.FILETYPE_PEM, 197 pemCertReq) 198 199 # Convert to ASN1 format expect by logon client call 200 asn1CertReq = crypto.dump_certificate_request( 201 crypto.FILETYPE_ASN1, 202 certReq) 188 203 else: 189 204 status = self.getStatusMessage(httplib.UNAUTHORIZED) … … 195 210 credentials = self.myProxyClient.logon(username, 196 211 password, 197 certReq= certReq)212 certReq=asn1CertReq) 198 213 status = self.getStatusMessage(httplib.OK) 199 214 response = '\n'.join(credentials) 200 215 201 except MyProxyClientError :216 except MyProxyClientError, e: 202 217 status = self.getStatusMessage(httplib.UNAUTHORIZED) 203 218 response = str(e) … … 220 235 221 236 return _myProxylogon 237 238 @staticmethod 239 def getStatusMessage(statusCode): 240 '''Make a standard status message for use with start_response 241 @type statusCode: int 242 @param statusCode: HTTP status code 243 @rtype: str 244 @return: status code with standard message 245 @raise KeyError: for invalid status code 246 ''' 247 return '%d %s' % (statusCode, httplib.responses[statusCode]) 248
Note: See TracChangeset
for help on using the changeset viewer.