Changeset 6950


Ignore:
Timestamp:
08/06/10 16:33:29 (9 years ago)
Author:
pjkersha
Message:

Incomplete - task 5: MyProxy? Logon HTTPS Interface

  • Finished epydoc ready for first release to PyPI.
Location:
TI12-security/trunk/MyProxyWebService
Files:
1 added
7 edited

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/MyProxyWebService/myproxy/server/test/myproxywsgi.ini

    r6945 r6950  
    2020paste.app_factory = myproxy.server.wsgi.app:MyProxyApp.app_factory 
    2121prefix = myproxy. 
     22 
     23# HTTP Basic Auth authentication realm used with MyProxy logon requests. 
    2224myproxy.httpbasicauth.realm = myproxy-realm 
     25 
     26# The key name in the WSGI environ dictionary which holds the MyProxy logon 
     27# function.  This is used by the HTTP Basic Auth middleware 
    2328myproxy.logon.logonFuncEnvKeyName = MYPROXY_LOGON_FUNC 
     29 
     30# Path for logon requests 
     31# 
     32# The URI path or paths that will be matched to a logobn request.  Regular 
     33# expression may be entered but typically only a single path would be expected 
     34# for the logon request.  The format of this option is inherited from the more 
     35# generic HTTP Basic Auth middleware which the MyProxyApp uses. 
    2436myproxy.logon.rePathMatchList = /logon 
     37 
     38# Path for get trust roots call.  This should be a single path.  Regular  
     39# expressions are not supported. 
    2540myproxy.getTrustRoots.path = /get-trustroots 
     41 
     42# MyProxy server which this MyProxy WSGI app is a client to.  Set here to the  
     43# fully qualified domain name or else set the MYPROXY_SERVER environment 
     44# variable.  See the documentation for the MyProxyClient egg for details 
    2645#myproxy.client.hostname = localhost 
    2746myproxy.client.caCertDir = /etc/grid-security/certificates 
  • TI12-security/trunk/MyProxyWebService/myproxy/server/test/test_httpbasicauth.py

    r6897 r6950  
    2222 
    2323class TestApp(object): 
     24    """Test WSGI Application for use with the unit tests for the HTTP Basic 
     25    Auth middleware developed for the myproxy.server.app.MyProxyApp application 
     26    """ 
    2427    def __init__(self, global_conf, **app_conf): 
    25         pass 
     28        """Follow standard Paste Deploy app factory function signature""" 
    2629     
    2730    def __call__(self, environ, start_response): 
     31        """Make a simple response for unit test code to trap and validate  
     32        against.  If this method is executed then the HTTP Basic Auth step in 
     33        the upstream middleware has succeeded. 
     34        """ 
    2835        contentType = 'text/plain' 
    2936        response = 'Authenticated!' 
     
    4552     
    4653    def __init__(self, app, global_conf, **app_conf): 
     54        """Follow standard Paste Deploy app factory function signature""" 
    4755        self.app = app 
    4856         
     
    7987     
    8088    def __init__(self, app, global_conf, **app_conf): 
     89        """Follow standard Paste Deploy app factory function signature""" 
    8190        self.app = app 
    8291         
    8392    def __call__(self, environ, start_response): 
     93        """Create HTTP Basic Auth callback""" 
    8494        def authenticate(environ, start_response, username, password): 
     95            """HTTP Basic Auth callback function""" 
    8596            if (username != self.__class__.USERNAME or 
    8697                password != self.__class__.PASSWORD): 
     
    93104 
    94105class HttpBasicAuthMiddlewareTestCase(unittest.TestCase): 
     106    """Unit tests for HTTP Basic Auth middleware used with the MyProxyWebService 
     107    package 
     108    """ 
    95109    CONFIG_FILE = 'httpbasicauth.ini' 
    96110     
    97111    def __init__(self, *args, **kwargs): 
     112        """Set-up Paste fixture from ini file settings""" 
    98113        here_dir = os.path.dirname(os.path.abspath(__file__)) 
    99114        configFilePath = ('config:%s' %  
  • TI12-security/trunk/MyProxyWebService/myproxy/server/test/test_myproxywsgi.cfg

    r6945 r6950  
    1313# 
    1414[MyProxyLogonAppTestCase.test01Logon] 
     15# Edit these setting for your own environment.  Password can be prompted for 
     16# from tty by commenting out or removing the password option here 
    1517username: pjk 
    1618password = mypassword 
     
    1820 
    1921[MyProxyLogonAppWithPasterTestCase.test02LogonScript] 
     22# Edit these setting for your own environment.  Password can be prompted for 
     23# from tty by commenting out or removing the password option here 
    2024username: pjk 
    2125password = mypassword 
  • TI12-security/trunk/MyProxyWebService/myproxy/server/test/test_myproxywsgi_with_paster.py

    r6945 r6950  
    2828class MyProxyLogonAppWithPasterTestCase(unittest.TestCase): 
    2929    """Test MyProxy Logon App WSGI in Paster web application server container 
     30    with bash shell script clients.  For POSIX-like systems ONLY 
    3031    """ 
    3132    THIS_DIR = path.dirname(__file__) 
     
    5152     
    5253    def __init__(self, *arg, **kw): 
     54        """Read settings from a config file and create thread for paster  
     55        based MyProxy Web Service app running over HTTPS 
     56        """ 
    5357        super(MyProxyLogonAppWithPasterTestCase, self).__init__(*arg, **kw) 
    5458        self.services = [] 
     
    123127        unit tests 
    124128         
    125         @param cfgFilePath: ini file containing configuration for the service 
    126         @type cfgFilePath: basestring 
    127         @param port: port number to run the service from 
    128         @type port: int 
     129        @param arg: tuple contains ini file path setting for the service 
     130        @type arg: tuple 
     131        @param kw: keywords including "port" - port number to run the service  
     132        from 
     133        @type kw: dict 
    129134        """ 
    130135        if self.disableServiceStartup: 
  • TI12-security/trunk/MyProxyWebService/myproxy/server/wsgi/httpbasicauth.py

    r6897 r6950  
    4545class HttpBasicAuthMiddleware(object): 
    4646    '''HTTP Basic Authentication Middleware  
     47 
     48    @cvar AUTHN_FUNC_ENV_KEYNAME: key name for referencing Authentication 
     49    callback function in environ.  Upstream middleware must set this. 
     50    @type AUTHN_FUNC_ENV_KEYNAME: string 
     51    @cvar AUTHN_FUNC_ENV_KEYNAME_OPTNAME: in file option name for setting the 
     52    Authentication callback environ key 
     53    @type AUTHN_FUNC_ENV_KEYNAME_OPTNAME: string 
     54    @cvar REALM_OPTNAME: ini file option name for setting the HTTP Basic Auth 
     55    authentication realm 
     56    @type REALM_OPTNAME: string 
     57    @cvar PARAM_PREFIX: prefix for ini file options 
     58    @type PARAM_PREFIX: string 
     59    @cvar AUTHENTICATE_HDR_FIELDNAME: HTTP header field name 'WWW-Authenticate' 
     60    @type AUTHENTICATE_HDR_FIELDNAME: string 
     61    @cvar AUTHENTICATE_HDR_FIELDNAME_LOWER: lowercase version of  
     62    AUTHENTICATE_HDR_FIELDNAME class variable included for convenience with 
     63    string matching  
     64    @type AUTHENTICATE_HDR_FIELDNAME_LOWER: string 
     65    @cvar AUTHN_SCHEME_HDR_FIELDNAME: HTTP Authentication scheme identifier 
     66    @type AUTHN_SCHEME_HDR_FIELDNAME: string 
     67    @cvar FIELD_SEP: field separator for username/password header string 
     68    @type FIELD_SEP: string 
     69    @cvar AUTHZ_ENV_KEYNAME: WSGI environ key name for HTTP Basic Auth header 
     70    content 
     71    @type AUTHZ_ENV_KEYNAME: string 
     72     
     73    @ivar __rePathMatchList: list of regular expression patterns used to match 
     74    incoming requests and enforce HTTP Basic Auth against 
     75    @type __rePathMatchList: list 
     76    @ivar __authnFuncEnvironKeyName: __authnFuncEnvironKeyName 
     77    @type __authnFuncEnvironKeyName: string 
     78    @ivar __realm: HTTP Basic Auth authentication realm 
     79    @type __realm: string 
     80    @ivar __app: next WSGI app/middleware in call chain 
     81    @type __app: function 
    4782    ''' 
    4883    AUTHN_FUNC_ENV_KEYNAME = ( 
     
    76111     
    77112    def __init__(self, app): 
     113        """Create instance variables 
     114        @param app: next middleware/app in WSGI stack 
     115        @type app: function 
     116        """ 
    78117        self.__rePathMatchList = None 
    79118        self.__authnFuncEnvironKeyName = None 
     
    92131        @type prefix: basestring 
    93132        @param prefix: prefix for configuration items 
    94         @type app_conf: dict         
    95         @param app_conf: PasteDeploy application specific configuration  
     133        @type local_conf: dict         
     134        @param local_conf: PasteDeploy application specific configuration  
    96135        dictionary 
     136        @rtype: myproxy.server.wsgi.httpbasicauth.HttpBasicAuthMiddleware 
     137        @return: an instance of this middleware 
    97138        """ 
    98139        httpBasicAuthFilter = cls(app) 
     
    125166 
    126167    def _getAuthnFuncEnvironKeyName(self): 
     168        """Get authentication callback function environ key name 
     169         
     170        @rtype: basestring 
     171        @return: callback function environ key name 
     172        """ 
    127173        return self.__authnFuncEnvironKeyName 
    128174 
    129175    def _setAuthnFuncEnvironKeyName(self, value): 
     176        """Set authentication callback environ key name 
     177         
     178        @type value: basestring 
     179        @param value: callback function environ key name 
     180        """ 
    130181        if not isinstance(value, basestring): 
    131182            raise TypeError('Expecting string type for ' 
    132183                            '"authnFuncEnvironKeyName"; got %r type' %  
    133184                            type(value)) 
     185             
    134186        self.__authnFuncEnvironKeyName = value 
    135187 
     
    141193 
    142194    def _getRePathMatchList(self): 
     195        """Get regular expression path match list 
     196         
     197        @rtype: tuple or list 
     198        @return: list of regular expressions used to match incoming request  
     199        paths and apply HTTP Basic Auth to 
     200        """ 
    143201        return self.__rePathMatchList 
    144202 
    145203    def _setRePathMatchList(self, value): 
     204        """Set regular expression path match list 
     205         
     206        @type value: tuple or list 
     207        @param value: list of regular expressions used to match incoming request  
     208        paths and apply HTTP Basic Auth to 
     209        """ 
    146210        if not isinstance(value, (list, tuple)): 
    147211            raise TypeError('Expecting list or tuple type for ' 
     
    156220 
    157221    def _getRealm(self): 
     222        """Get realm 
     223         
     224        @rtype: basestring 
     225        @return: HTTP Authentication realm to set in responses 
     226        """ 
    158227        return self.__realm 
    159228 
    160229    def _setRealm(self, value): 
     230        """Set realm 
     231         
     232        @type value: basestring 
     233        @param value: HTTP Authentication realm to set in responses 
     234        """ 
    161235        if not isinstance(value, basestring): 
    162236            raise TypeError('Expecting string type for ' 
     
    188262    def _parseCredentials(self, environ): 
    189263        """Extract username and password from HTTP_AUTHORIZATION environ key 
     264         
     265        @param environ: WSGI environ dict 
     266        @type environ: dict 
    190267         
    191268        @rtype: tuple 
     
    222299        @return: response 
    223300        @rtype: iterable 
     301        @raise HttpBasicAuthMiddlewareConfigError: no authentication callback 
     302        found in environ 
    224303        """ 
    225304        log.debug("HttpBasicAuthNMiddleware.__call__ ...") 
     
    296375        @param contentType: set 'Content-type' HTTP header field - defaults to 
    297376        'text/plain' 
     377        @rtype: list 
     378        @return: HTTP error response 
    298379        '''                         
    299380        status = '%d %s' % (code, httplib.responses[code]) 
  • TI12-security/trunk/MyProxyWebService/myproxy/server/wsgi/middleware.py

    r6943 r6950  
    3333 
    3434class MyProxyClientMiddlewareBase(object): 
    35     """Base class for common functionality""" 
    36     __slots__ = ('__app', '__clientEnvironKeyName',) 
     35    """Base class for common functionality 
     36     
     37    @cvar CLIENT_ENV_KEYNAME_OPTNAME: ini file option which sets the key name 
     38    in the WSGI environ for referring to the MyProxy client instance shared 
     39    between MyProxy* middleware/apps 
     40    @type CLIENT_ENV_KEYNAME_OPTNAME: string 
     41     
     42    @cvar DEFAULT_CLIENT_ENV_KEYNAME: default value for key name set in the 
     43    WSGI environ dict which refers to the MyProxy client instance shared 
     44    between MyProxy* middleware/apps 
     45    @type DEFAULT_CLIENT_ENV_KEYNAME: string 
     46     
     47    @ivar __app: WSGI callable for next middleware or app in the WSGI stack 
     48    @type __app: function 
     49     
     50    @ivar __clientEnvironKeyName: key name set in the WSGI environ dict which  
     51    refers to the MyProxy client instance shared between MyProxy* middleware/ 
     52    apps 
     53    @type __clientEnvironKeyName: string 
     54    """ 
     55    __slots__ = ( 
     56        '__app',  
     57        '__clientEnvironKeyName', 
     58    ) 
    3759     
    3860    CLIENT_ENV_KEYNAME_OPTNAME = 'clientEnvKeyName' 
     
    4163         
    4264    def __init__(self, app): 
     65        """Create WSGI app and MyProxy client attributes 
     66        @type app: function 
     67        @param app: WSGI callable for next middleware or app in the WSGI stack 
     68        """ 
    4369        self.__app = app 
    4470        self.__clientEnvironKeyName = None 
     
    82108        @type statusCode: int 
    83109        @param statusCode: HTTP status code 
    84         @rtype: str 
     110        @rtype: string 
    85111        @return: status code with standard message 
    86112        @raise KeyError: for invalid status code 
     
    90116     
    91117class MyProxyClientMiddleware(MyProxyClientMiddlewareBase): 
    92     ''' 
    93     Create a MyProxy client and make it available to other middleware in the  
     118    '''Create a MyProxy client and make it available to other middleware in the  
    94119    WSGI stack 
     120     
     121    @cvar LOGON_FUNC_ENV_KEYNAME_OPTNAME: ini file option name to set the key  
     122    name in WSGI environ dict to assign to the Logon function created by this 
     123    middleware 
     124    @type LOGON_FUNC_ENV_KEYNAME_OPTNAME: string 
     125     
     126    @cvar DEFAULT_LOGON_FUNC_ENV_KEYNAME: default value for the key name in  
     127    WSGI environ dict to assign to the Logon function created by this 
     128    middleware 
     129    @type DEFAULT_LOGON_FUNC_ENV_KEYNAME: string 
     130     
     131    @cvar CERT_REQ_POST_PARAM_KEYNAME: HTTP POST field name for the  
     132    certificate request posted in logon calls 
     133    @type CERT_REQ_POST_PARAM_KEYNAME: string 
     134     
     135    @cvar PARAM_PREFIX: prefix for ini file option names  
     136    @type PARAM_PREFIX: string 
     137     
     138    @cvar MYPROXY_CLIENT_PARAM_PREFIX: default value for ini file sub-prefix  
     139    used for MyProxyClient initialisation settings such as MyProxy server  
     140    hostname, CA cert directory etc.  The prefix is such that option names  
     141    will look like this e.g. 
     142    <PARAM_PREFIX><MYPROXY_CLIENT_PARAM_PREFIX>hostname 
     143    ... 
     144    @type MYPROXY_CLIENT_PARAM_PREFIX: string 
     145     
     146    @ivar __myProxyClient: MyProxy client interface object to enable this 
     147    middleware to communicate with a backend MyProxy server using the MyProxy 
     148    protocol 
     149    @type __myProxyClient: myproxy.client.MyProxyClient 
     150     
     151    @ivar __logonFuncEnvironKeyName:  
     152    @type __logonFuncEnvironKeyName: string 
    95153    ''' 
    96154    # Options for ini file 
     
    108166     
    109167    __slots__ = ( 
    110         '__app', 
    111168        '__myProxyClient',  
    112169        '__logonFuncEnvironKeyName', 
     
    136193        @type prefix: basestring 
    137194        @param prefix: prefix for configuration items 
     195        @type myProxyClientPrefix: ini file sub-prefix used for MyProxyClient  
     196        initialisation settings such as MyProxy server  hostname, CA cert.  
     197        directory etc.   
     198        @param myProxyClientPrefix: basestring 
    138199        @type app_conf: dict         
    139200        @param app_conf: PasteDeploy application specific configuration  
    140201        dictionary 
     202         
     203        @rtype: myproxy.server.wsgi.middleware.MyProxyClientMiddleware 
     204        @return: an instance of this application 
    141205        """ 
    142206        app = cls(app) 
     
    152216        @type prefix: basestring 
    153217        @param prefix: prefix for configuration items 
    154         @type prefix: basestring 
    155         @param prefix: explicit prefix for MyProxyClient class specific  
    156         configuration items 
     218        @type myProxyClientPrefix: basestring 
     219        @param myProxyClientPrefix: explicit prefix for MyProxyClient class  
     220        specific configuration items 
    157221        @type app_conf: dict         
    158222        @param app_conf: PasteDeploy application specific configuration  
     
    247311        """Return the MyProxy logon method wrapped as a HTTP Basic Auth  
    248312        authenticate interface function 
     313         
     314        @rtype: function 
     315        @return: MyProxy logon HTTP Basic Auth Callback 
    249316        """ 
    250317        def _myProxylogon(environ, start_response, username, password): 
    251318            """Wrap MyProxy logon method as a WSGI app 
     319            @type environ: dict 
     320            @param environ: WSGI environment variables dictionary 
     321            @type start_response: function 
     322            @param start_response: standard WSGI start response function 
     323            @type username: basestring 
     324            @param username: username credential to MyProxy logon 
     325            @type password: basestring 
     326            @param password: pass-phrase for MyProxy logon call 
     327            @raise HttpBasicAuthResponseException: invalid client request 
     328            @raise MyProxyClientMiddlewareError: socket error for backend 
     329            MyProxy server 
    252330            """   
    253331            requestMethod = environ.get('REQUEST_METHOD')              
     
    323401    upstream in the WSGI stack to set up a MyProxyClient instance and make it  
    324402    available in the environ to call its getTrustRoots method. 
     403     
     404    @cvar PATH_OPTNAME: ini file option to set the URI path for this service 
     405    @type PATH_OPTNAME: string 
     406     
     407    @cvar DEFAULT_PATH: default URI path setting 
     408    @type DEFAULT_PATH: string 
     409 
     410    @cvar PARAM_PREFIX: prefix for ini file option names  
     411    @type PARAM_PREFIX: string 
     412     
     413    @ivar __path: URI path setting for this service 
     414    @type __path: basestring 
    325415    """ 
    326      
    327     # Options for ini file 
    328     CLIENT_ENV_KEYNAME_OPTNAME = \ 
    329         MyProxyClientMiddleware.CLIENT_ENV_KEYNAME_OPTNAME 
    330416         
    331417    PATH_OPTNAME = 'path'      
    332      
    333     DEFAULT_CLIENT_ENV_KEYNAME = \ 
    334         MyProxyClientMiddleware.DEFAULT_CLIENT_ENV_KEYNAME 
    335      
    336418    DEFAULT_PATH = '/myproxy/get-trustroots' 
    337419     
     
    366448        @param app_conf: PasteDeploy application specific configuration  
    367449        dictionary 
     450         
     451        @rtype: myproxy.server.wsgi.middleware.MyProxyGetTrustRootsMiddleware 
     452        @return: an instance of this middleware 
    368453        """ 
    369454        app = cls(app) 
     
    421506        @type start_response: function 
    422507        @param start_response: standard WSGI start response function 
     508         
     509        @rtype: list 
     510        @return: get trust roots response 
    423511        ''' 
    424512        # Skip if path doesn't match 
     
    463551         
    464552        @rtype: basestring 
    465         @return: trust roots formatted as a HTTP response 
     553        @return: trust roots base64 encoded and concatenated together 
     554        @raise MyProxyGetTrustRootsMiddlewareError: socket error with backend 
     555        MyProxy server 
     556        @raise MyProxyClientError: error response received by MyProxyClient 
     557        instance 
    466558        """ 
    467559        try: 
  • TI12-security/trunk/MyProxyWebService/setup.py

    r6938 r6950  
    2020 
    2121setup( 
    22     name =              'MyProxyServerUtils', 
     22    name =              'MyProxyWebService', 
    2323    version =           '0.1.0', 
    24     description =       'MyProxy Server Utilities', 
    25     long_description =  '''Provides a HTTPS interface to myproxy-logon  
    26 implemented as a WSGI application fronting calls to a MyProxy server. 
    27      
    28 MyProxy is an application available from the Globus Toolkit which enables the 
    29 management of PKI based credentials. 
     24    description =       'MyProxy Web Service', 
     25    long_description =  '''\ 
     26Provides a simple web service interface to MyProxy.  MyProxy is a Service for  
     27managing PKI based credentials which is part of the Globus Toolkit.  Providing 
     28a HTTP based interface enables HTTP based clients to connect to a MyProxy server 
     29and retrieve credentials. 
     30 
     31The interface is implemented as a WSGI application which fronts a normal  
     32MyProxy server.  myproxy-logon and myproxy-get-trustroots are expressed as web  
     33service calls.  The WSGI application forwards the requests on to the MyProxy  
     34server over the usual MyProxy protocol.  The web service interface is RESTful  
     35using GET and POST operations and the logon interface makes uses of HTTP Basic  
     36Auth to pass username and pass-phrase credentials.  The service is hosted over  
     37HTTPS. 
     38 
     39The unit tests include a test application served using paster.  Client scripts 
     40are also available which need no specialised installation or applications, only 
     41openssl and curl which are typically available on Linux/UNIX based systems. 
    3042    ''', 
    3143    author =            'Philip Kershaw', 
     
    3345    maintainer =        'Philip Kershaw', 
    3446    maintainer_email =  'Philip.Kershaw@stfc.ac.uk', 
    35     url =               'http://proj.badc.rl.ac.uk/ndg/wiki/Security/MyProxyClient', 
     47    url =               'http://proj.badc.rl.ac.uk/ndg/wiki/Security/MyProxyWebService', 
    3648    platforms =         ['POSIX', 'Linux', 'Windows'], 
    3749    install_requires =  ['PasteDeploy',  
     
    4658    }, 
    4759    classifiers = [ 
    48         'Development Status :: 5 - Production/Stable', 
     60        'Development Status :: 3 - Alpha', 
    4961        'Environment :: Console', 
    5062        'Environment :: Web Environment', 
Note: See TracChangeset for help on using the changeset viewer.