Changeset 2748


Ignore:
Timestamp:
26/07/07 16:55:08 (12 years ago)
Author:
pjkersha
Message:

called by HandleSecurity? function. Needs testing and fixes - see TODOs

ows_server/ows_server/config/ndgDiscovery.config:

  • added a section for security including WS-Security and SSL PKI settings.

ows_server/ows_server/config/routing.py:

  • added entry for login handling

ws_server/ows_server/controllers/login.py:

  • security web services integrated. TODO: credentials passing across http

redirect

ows_server/ows_server/controllers/logout.py:

  • security WS calls integrated

ows_server/ows_server/templates/ndgPage.kid:

  • fix to display of roles

ows_server/ows_server/templates/login.kid:

  • new page for login
Location:
TI05-delivery/ows_framework/trunk/ows_server/ows_server
Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • TI05-delivery/ows_framework/trunk/ows_server/ows_server/config/ndgDiscovery.config

    r2736 r2748  
    106106npm.ac.uk: pgsql.npm.ac.uk 
    107107 
     108[NDG_SECURITY] 
     109# Debug e.g. open(<somefile>, 'w') 
     110#tracefile: None 
     111tracefile: sys.stderr 
     112 
     113# Service addresses 
     114#sessionMgrURI: https://localhost:5700/SessionManager 
     115sessionMgrURI: https://glue.badc.rl.ac.uk:50000/SessionManager 
     116#attAuthorityURI: http://localhost:5000/AttributeAuthority 
     117attAuthorityURI: http://glue.badc.rl.ac.uk/services/ndg/security/AttributeAuthority 
     118 
     119# WS-Security signature handler 
     120# 
     121# X.509 certificate sent with outbound signed messages 
     122wssCertFilePath: Junk-cert.pem 
     123 
     124# Private key used to sign messages 
     125wssKeyFilePath: Junk-key.pem 
     126 
     127# Password for private key - comment out if the file is not password protected 
     128wssKeyPwd:  
     129 
     130# Space separated list of CA cert. files to validate certs against when 
     131# verifying responses 
     132wssCACertFilePathList = cacert.pem 
     133 
     134# SSL Connections 
     135# 
     136# Space separated list of CA cert. files.  The peer cert. 
     137# must verify against at least one of these otherwise the connection is  
     138# dropped. 
     139sslCACertFilePathList: cacert.pem 
     140 
     141# Set an alternate CommonName to match with peer cert for SSL 
     142# Connections.  If the CN=hostname of the peer then this option  
     143# can be commented out 
     144#sslPeerCertCN:  
     145 
     146# Attribute Certificate  
     147# Issuer name - should match with name element specified in  
     148# home Attribute Authority's attAuthorityProperties.xml 
     149acIssuerName: BADC 
     150 
     151# verification of X.509 cert back to CA 
     152acCACertFilePathList: cacert.pem 
    108153 
    109154[RELATED] 
  • TI05-delivery/ows_framework/trunk/ows_server/ows_server/config/routing.py

    r2740 r2748  
    3838    # following is the shell for the rest of the ndg  
    3939    map.connect('login', controller='login') 
     40    map.connect('getCredentials', controller='login', action='getCredentials') 
    4041    map.connect('wayf', controller='login', action='wayf') 
    4142    map.connect('logout', controller='logout') 
  • TI05-delivery/ows_framework/trunk/ows_server/ows_server/controllers/login.py

    r2709 r2748  
     1import sys 
    12from ows_server.lib.base import * 
     3from ows_common.exception_report import OwsError 
    24from paste.request import parse_querystring 
     5 
     6from ndg.security.common.AttAuthority import AttAuthorityClient 
     7from ndg.security.common.SessionMgr import SessionMgrClient, \ 
     8    AttributeRequestDenied 
     9 
    310 
    411class LoginController(BaseController): 
     
    1724        else: 
    1825            c.returnTo='' 
     26 
     27    def __securitySetup(self): 
     28        '''PKI settings for Attribute Authority and Session Manager''' 
     29         
     30        self.ndgCfg = request.environ['ndgConfig'] 
     31 
     32        tracefileExpr = self.ndgCfg.get('NDG_SECURITY', 'tracefile') 
     33        if tracefileExpr: 
     34            self.tracefile = eval(tracefileExpr) 
     35         
     36        # ... for SSL connections to security web services 
     37        try: 
     38            self.sslCACertFilePathList = \ 
     39            self.ndgCfg.get('NDG_SECURITY', 'sslCACertFilePathList').split() 
     40                 
     41        except AttributeError: 
     42            raise OwsError, 'No "sslCACertFilePathList" security setting' 
     43 
     44        self.sslPeerCertCN = self.ndgCfg.get('NDG_SECURITY', 'sslPeerCertCN') 
     45 
     46        # ...and for WS-Security digital signature 
     47        self.wssCertFilePath = self.ndgCfg.get('NDG_SECURITY',  
     48                                               'wssCertFilePath') 
     49        self.wssPriKeyFilePath = self.ndgCfg.get('NDG_SECURITY',  
     50                                                 'wssKeyFilePath') 
     51        self.wssPriKeyPwd = self.ndgCfg.get('NDG_SECURITY', 'wssKeyPwd') 
     52 
     53        try: 
     54            self.wssCACertFilePathList = \ 
     55            self.ndgCfg.get('NDG_SECURITY', 'wssCACertFilePathList').split() 
     56                 
     57        except AttributeError: 
     58            raise OwsError, 'No "wssCACertFilePathList" security setting' 
     59 
    1960     
    2061    def index(self): 
    2162        ''' Ok, you really want to login here ''' 
    2263        self.__setup() 
     64 
     65        return render_response('login') 
     66 
     67 
     68    def getCredentials(self): 
     69        """Authenticate user and cache user credentials in 
     70        Session Manager following user login""" 
    2371         
    24         # fudge for now 
    25         session['ndgSec']={'h':'badc.nerc.ac.uk','u':'lawrence','r':['all']} 
     72        self.__setup() 
     73        self.__securitySetup() 
     74         
     75        if not hasattr(self, "smClnt"): 
     76            smURI = self.ndgCfg.get('NDG_SECURITY', 'sessionMgrURI') 
     77 
     78            # May be better as a 'g' global set-up at start-up? 
     79            # 
     80            # tracefile could be removed for production use 
     81            self.smClnt = SessionMgrClient(uri=smURI, 
     82                            sslCACertFilePathList=self.sslCACertFilePathList, 
     83                            sslPeerCertCN=self.sslPeerCertCN, 
     84                            signingCertFilePath=self.wssCertFilePath, 
     85                            signingPriKeyFilePath=self.wssPriKeyFilePath, 
     86                            signingPriKeyPwd=self.wssPriKeyPwd, 
     87                            caCertFilePathList=self.wssCACertFilePathList, 
     88                            tracefile=self.tracefile)        
     89         
     90        username = request.params['username'] 
     91        passphrase = request.params['passphrase'] 
     92         
     93        # Connect to Session Manager 
     94        try: 
     95            proxyCert, proxyPriKey, userCert, sessID = \ 
     96                        self.smClnt.connect(username, passphrase=passphrase) 
     97        except Exception, e: 
     98            c.xml = "Error logging in: %s" % e 
     99            return render_response('login') 
     100         
     101        # Cache user attributes in Session Manager 
     102        try: 
     103            # Set the Attribute Authority address for the Session Manager to 
     104            # send its attribute request to 
     105            aaURI = self.ndgCfg.get('NDG_SECURITY', 'attAuthorityURI') 
     106 
     107            # Reset signature handler to authenticate client using user 
     108            # proxy cert returned from connect call 
     109            self.smClnt.signatureHandler.reqBinSecTokValType = 'X509PKIPathv1' 
     110            self.smClnt.signatureHandler.signingPriKey = proxyPriKey                
     111            wssCertChain = (userCert, proxyCert)     
     112            self.smClnt.signatureHandler.signingCertChain = wssCertChain 
     113 
     114            # Make request for attribute certificate 
     115            attCert = self.smClnt.getAttCert(attAuthorityURI=aaURI) 
     116 
     117        except AttributeRequestDenied, e: 
     118            c.xml = "No roles available: %s" % e 
     119            return render_response('login') 
     120             
     121        except Exception, e: 
     122            c.xml = "Error getting roles: %s" % e 
     123            return render_response('login') 
     124 
     125        # Make session 
     126        # 
     127        # Security credentials - proxyCert, userCert, ProxyPriKey and sessID 
     128        # could be held in the session but how secure is 
     129        # the session - where is it visible? 
     130        # 
     131        # P J Kershaw 25/07/07 
     132        session['ndgSec']={'h':'badc.nerc.ac.uk', 
     133                           'u':username, 
     134                           'r':attCert.roles, 
     135                           'sessID':sessID, 
     136                           'wssCertChain':wssCertChain, 
     137                           'wssPriKey':proxyPriKey, 
     138                           'smURI':smURI} 
    26139        session['panelView']='History' 
    27140        session.save() 
     141        
     142        # Make a security cookie here ... 
     143         
     144        # Need to pass security creds back to requestor so that they can make 
     145        # a cookie.  If the requestor is in the same domain as the login then 
     146        # this is not necessary. 
    28147         
    29148        # and now go back to whence we had come 
     
    33152            h.redirect_to(c.returnTo) 
    34153        else: 
    35             c.xml='<p> Login Successful </p>' 
     154            c.xml='Login Successful' 
    36155            return render_response('content') 
    37156             
     
    40159         
    41160        self.__setup() 
     161        self.__securitySetup() 
    42162         
    43163        #currently fudge this 
     
    50170            pass 
    51171         
     172        if not hasattr(self, "aaClnt"): 
     173            aaURI = self.ndgCfg.get('NDG_SECURITY', 'attAuthorityURI') 
     174 
     175            # May be better as a 'g' global set-up at start-up? 
     176            # 
     177            # tracefile could be removed for production use 
     178            self.aaClnt = AttAuthorityClient(uri=aaURI, 
     179                                signingCertFilePath=self.wssCertFilePath, 
     180                                signingPriKeyFilePath=self.wssPriKeyFilePath, 
     181                                signingPriKeyPwd=self.wssPriKeyPwd, 
     182                                caCertFilePathList=self.wssCACertFilePathList, 
     183                                tracefile=self.tracefile) 
     184 
     185        # Get list of login uris for trusted sites including THIS one 
     186        trustedHosts = self.aaClnt.getTrustedHostInfo() 
     187        thisHost = self.aaClnt.getHostInfo() 
     188         
     189        try: 
     190            trustedHosts[thisHost.keys()[0]] = thisHost.values()[0] 
     191        except TypeError: 
     192            raise OwsError, \ 
     193                        "thisHost returned from Attribute Authority is empty"  
     194             
     195        c.providers=dict([(k,v['loginURI']) for k,v in trustedHosts.items()]) 
     196         
    52197        return render_response('wayf') 
    53198         
  • TI05-delivery/ows_framework/trunk/ows_server/ows_server/controllers/logout.py

    r2695 r2748  
    11from ows_server.lib.base import * 
    22from paste.request import parse_querystring 
     3import sys # include in case tracefile is set to sys.stderr  
     4 
     5from ndg.security.common.SessionMgr import SessionMgrClient 
     6 
     7 
    38class LogoutController(BaseController): 
    49    ''' Provides the pylons controller for logging out and killing the cookies ''' 
     
    1116        else: 
    1217            c.returnTo='' 
     18 
     19        self.__securitySetup() 
     20         
     21         
     22    def __securitySetup(self): 
     23        '''PKI settings for Session Manager''' 
     24         
     25        self.ndgCfg = request.environ['ndgConfig'] 
     26 
     27        tracefileExpr = self.ndgCfg.get('NDG_SECURITY', 'tracefile') 
     28        if tracefileExpr: 
     29            self.tracefile = eval(tracefileExpr) 
     30         
     31        # ... for SSL connections to security web services 
     32        try: 
     33            self.sslCACertFilePathList = \ 
     34            self.ndgCfg.get('NDG_SECURITY', 'sslCACertFilePathList').split() 
     35                 
     36        except AttributeError: 
     37            raise OwsError, 'No "sslCACertFilePathList" security setting' 
     38 
     39        self.sslPeerCertCN = self.ndgCfg.get('NDG_SECURITY', 'sslPeerCertCN') 
     40 
     41        # ...and for WS-Security digital signature 
     42        self.wssCertFilePath = self.ndgCfg.get('NDG_SECURITY',  
     43                                               'wssCertFilePath') 
     44        self.wssPriKeyFilePath = self.ndgCfg.get('NDG_SECURITY',  
     45                                                 'wssKeyFilePath') 
     46        self.wssPriKeyPwd = self.ndgCfg.get('NDG_SECURITY', 'wssKeyPwd') 
     47 
     48        try: 
     49            self.wssCACertFilePathList = \ 
     50            self.ndgCfg.get('NDG_SECURITY', 'wssCACertFilePathList').split() 
     51                 
     52        except AttributeError: 
     53            raise OwsError, 'No "wssCACertFilePathList" security setting' 
     54 
    1355     
    1456    def index(self): 
    1557        ''' Ok, you really want to logout here ''' 
    1658        self.__setup() 
     59 
     60        # If the user logged in locally, their proxy cert will be available  
     61        # stored in the session object.  This can be used to authenticate in  
     62        # the disconnect request. 
     63        wssCertChain = session['ndgSec'].get('wssCertChain') 
     64         
     65        # Look into the session and go kill the wallet 
     66        if not hasattr(self, "smClnt"): 
     67            smURI = self.ndgCfg.get('NDG_SECURITY', 'sessionMgrURI') 
     68 
     69            # May be better as a 'g' global set-up at start-up? 
     70            # 
     71            # tracefile could be removed for production use 
     72            self.smClnt = SessionMgrClient(uri=smURI, 
     73                            sslCACertFilePathList=self.sslCACertFilePathList, 
     74                            sslPeerCertCN=self.sslPeerCertCN, 
     75                            signingCertChain=wssCertChain, 
     76                            signingCertFilePath=self.wssCertFilePath, 
     77                            signingPriKeyFilePath=self.wssPriKeyFilePath, 
     78                            signingPriKeyPwd=self.wssPriKeyPwd, 
     79                            caCertFilePathList=self.wssCACertFilePathList, 
     80                            tracefile=self.tracefile)        
     81 
     82        # Set authentication method for Session Manager.  If a 
     83        # proxy cert is available in the session then this can be used, 
     84        # otherwise use the session ID 
     85        if wssCertChain: 
     86            sessID = None 
     87            self.smClnt.signatureHandler.reqBinSecTokValType = 'X509PKIPathv1' 
     88            self.smClnt.signatureHandler.signingPriKey = \ 
     89                                                session['ndgSec']['wssPriKey']                
     90        else: 
     91            sessID = session['ndgSec']['sessID'] 
     92             
     93        # Disconnect from Session Manager 
     94        try: 
     95            self.smClnt.disconnect(sessID=sessID) 
     96        except Exception, e: 
     97            c.xml = "Error disconnecting: %s" % e 
    1798         
    1899        # easy to kill our cookie 
     
    21102         
    22103        session.save() 
    23         
    24         # but now we should look into the session and go kill the wallet 
    25          
     104 
     105                
    26106        # and now go back to whence we had come 
    27107        h.redirect_to(c.returnTo) 
  • TI05-delivery/ows_framework/trunk/ows_server/ows_server/models/ndgSecurity.py

    r2641 r2748  
    1 def HandleSecurity(securityElement,securityTokens): 
    2     if securityTokens is not None: 
    3         status=1 
    4         message='Access Allowed' 
    5     else: 
    6         status=0 
    7         message='Not Logged in' 
    8     return status,message 
     1from ows_common.exception_report import OwsError 
     2from ndg.security.common.SessionMgr import SessionMgrClient, \ 
     3    AttributeRequestDenied 
     4 
     5def HandleSecurity(securityElement, securityTokens): 
     6    return SecurityHandler(securityElement, securityTokens)() 
     7 
     8# This is an initial implementation and is untested.  See TODOs 
     9# for more info 
     10# 
     11# P J Kershaw 26/07/07 
     12class SecurityHandler(object): 
     13    """Make access control decision based on CSML constraint and user security 
     14    token""" 
     15     
     16    AccessAllowedMsg = "Access Allowed" 
     17    AccessDeniedMsg = "Access Denied" 
     18    NotLoggedInMsg = 'Not Logged in' 
     19     
     20    def __init__(self, securityElement, securityTokens): 
     21        """Initialise settings for WS-Security and SSL for SOAP 
     22        call to Session Manager 
     23         
     24        @type: ? TODO: set type 
     25        @param securityElement: CSML security constraint containing role and 
     26        Attribute Authority URI 
     27         
     28        @type: pylons.session 
     29        @param securityTokens: dict-like session object containing security  
     30        tokens""" 
     31         
     32        self.securityElement = securityElement 
     33        self.securityTokens = securityTokens 
     34         
     35        # TODO: fix this ref. 
     36        self.ndgCfg = request.environ['ndgConfig'] 
     37 
     38        self.tracefile = eval(self.ndgCfg.get('NDG_SECURITY','tracefile')) 
     39         
     40        # ... for SSL connections to security web services 
     41        try: 
     42            self.sslCACertFilePathList = \ 
     43            self.ndgCfg.get('NDG_SECURITY','sslCACertFilePathList').split() 
     44                 
     45        except AttributeError: 
     46            raise OwsError, 'No "sslCACertFilePathList" security setting' 
     47 
     48        self.sslPeerCertCN = self.ndgCfg.get('NDG_SECURITY', 'sslPeerCertCN') 
     49 
     50        # ...and for WS-Security digital signature 
     51        self.wssCertFilePath = self.ndgCfg.get('NDG_SECURITY',  
     52                                               'wssCertFilePath') 
     53        self.wssPriKeyFilePath = self.ndgCfg.get('NDG_SECURITY',  
     54                                                 'wssKeyFilePath') 
     55        self.wssPriKeyPwd = self.ndgCfg.get('NDG_SECURITY', 'wssKeyPwd') 
     56 
     57        try: 
     58            self.wssCACertFilePathList = \ 
     59            self.ndgCfg.get('NDG_SECURITY', 'wssCACertFilePathList').split() 
     60                 
     61        except AttributeError: 
     62            raise OwsError, 'No "wssCACertFilePathList" security setting' 
     63 
     64        # Attribute Certificate verification of X.509 cert chain back to CA 
     65        try: 
     66            self.acCACertFilePathList = \ 
     67            self.ndgCfg.get('NDG_SECURITY', 'acCACertFilePathList').split() 
     68                 
     69        except AttributeError: 
     70            raise OwsError, 'No "wssCACertFilePathList" security setting' 
     71 
     72        # Create Session Manager client 
     73        self.smClnt = SessionMgrClient(uri=self.securityTokens['smURI'], 
     74                        sslCACertFilePathList=self.sslCACertFilePathList, 
     75                        sslPeerCertCN=self.sslPeerCertCN, 
     76                        signingCertChain=securityTokens.get('wssCertChain'), 
     77                        signingCertFilePath=self.wssCertFilePath, 
     78                        signingPriKeyFilePath=self.wssPriKeyFilePath, 
     79                        signingPriKeyPwd=self.wssPriKeyPwd, 
     80                        caCertFilePathList=self.wssCACertFilePathList, 
     81                        tracefile=self.tracefile)        
     82 
     83        # Fix WS-Security BinarySecurityToken Value Type for the passing of a  
     84        # cert chain - required for use with proxy cert. 
     85        if wssCertChain: 
     86            self.smClnt.signatureHandler.reqBinSecTokValType = 'X509PKIPathv1' 
     87 
     88 
     89    def __call__(self, **kw): 
     90        """Convenience wrapper for checAccess""" 
     91        return self.checkAccess(**kw) 
     92 
     93 
     94    def checkAccess(self, securityElement=None, securityTokens=None): 
     95        """Make an access control decision based on whether the user is 
     96        authenticated and has the required roles 
     97         
     98        @type: ? TODO: set type 
     99        @keyword securityElement: CSML security constraint containing role and 
     100        Attribute Authority URI.  Resets equivalent object attribute. 
     101         
     102        @type: pylons.session 
     103        @keyword securityTokens: dict-like session object containing security  
     104        tokens.  Resets equivalent object attribute.""" 
     105      
     106        if securityElement: 
     107            self.securityElement = securityElement 
     108             
     109        if securityTokens: 
     110            self.securityTokens = securityTokens 
     111              
     112        if self.securityTokens is not None: 
     113            return self.__checkAccess() 
     114        else: 
     115            return False, self.__class__.NotLoggedInMsg 
     116 
     117    
     118    def __checkAttCert(self): 
     119        """Check to see if the Session Manager can deliver an Attribute  
     120        Certificate with the required role to gain access to the resource 
     121        in question""" 
     122         
     123        try: 
     124            # Get the Attribute Authority address for the Session Manager to 
     125            # send its attribute request to 
     126            # 
     127            # # TODO: get the correct AA URI attribute name 
     128            aaURI = self.securityElement.aaURI  
     129 
     130            # Make request for attribute certificate 
     131            # 
     132            # sessID is needed if proxy cert is unavailable as ID 
     133            # 
     134            # TODO: get correct role name attribute from securityElement var 
     135            attCert = self.smClnt.getAttCert(attAuthorityURI=aaURI, 
     136                                     sessID=self.securityToken.get('sessID'), 
     137                                     reqRole=self.securityElement.roleName) 
     138 
     139        except AttributeRequestDenied, e: 
     140            return False, self.__class__.AccessDeniedMsg 
     141         
     142        # Check attribute certificate is valid 
     143        attCert.certFilePathList = self.acCACertFilePathList 
     144        attCert.isValid(raiseExcep=True) 
     145             
     146        # Check it's issuer is as expected 
     147        if attCert.issuerName != self.acIssuerName: 
     148            raise OwsError, "Attribute Certificate issuer must match " + \ 
     149                "this data provider's Attribute Authority name id" 
     150                        
     151        return True, self.__class__.AccessAllowedMsg 
     152         
  • TI05-delivery/ows_framework/trunk/ows_server/ows_server/templates/ndgPage.kid

    r2688 r2748  
    100100                        <!--! now we choose one of the next two (logged in or not) --> 
    101101                        <div py:if="'ndgSec' in session"><table><tbody><tr><td> User [${session['ndgSec']['u']}] logged in 
    102                         at [${session['ndgSec']['h']}] with roles [${session['ndgSec']['r']}]</td><td> 
     102                        at [${session['ndgSec']['h']}] with roles [${', '.join(session['ndgSec']['r'])}]</td><td> 
    103103                        &nbsp;<span py:replace="logOut()"/></td></tr></tbody></table></div> 
    104104                        <div py:if="'ndgSec' not in session">Further services maybe available if you can 
Note: See TracChangeset for help on using the changeset viewer.