Ignore:
Timestamp:
14/07/06 11:34:15 (14 years ago)
Author:
pjkersha
Message:

Tests/SecurityClientTest?.py: change test defaults
share/ndg-*: clean up tab indents
www/cgi-bin/security.py: updated from cgi-bin test versions used in alpha tests.
NDG/SecurityCGI.py: modified some method names to include '_' prefix to highlight that they're not part of the
external interface.

NDG/SecurityClient.py: include explicit catch for HTTPResponse exception from ZSI ServiceProxy? - this error
is normally related to WSDL URI not found.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/python/www/cgi-bin/security.py

    r751 r1300  
    11#!/usr/local/NDG/ActivePython-2.4/bin/python 
    2 """NDG CGI security script 
    3   
     2 
     3"""Example NDG Security CGI service based on SecurityCGI base class 
     4 
    45NERC Data Grid Project 
    5   
    6 P J Kershaw 14/09/05 
    7   
    8 Copyright (C) 2005 CCLRC & NERC 
    9   
     6 
     7P J Kershaw 25/05/06 
     8 
     9Copyright (C) 2006 CCLRC & NERC 
     10 
    1011This software may be distributed under the terms of the Q Public License, 
    1112version 1.0 or later. 
    1213""" 
    1314import os 
    14 import sys 
    15 import cgi 
    16 import re 
    17  
    18 # Catch socket errors 
    19 import socket 
    20  
    21 from Cookie import SimpleCookie 
    22 from ZSI import ServiceProxy 
    23  
    24  
    25 from NDG.AttCert import * 
    26 from NDG.SessionClient import * 
    27  
    28  
    29 #_____________________________________________________________________________ 
    30 class SecurityCGIError(Exception): 
    31  
    32     def __init__(self, msg): 
    33  
    34         self.__msg = msg 
    35  
    36     def __str__(self): 
    37         return self.__msg 
    38  
    39  
    40 #_____________________________________________________________________________ 
    41 class SecurityCGI: 
    42     """CGI for NDG authentication and authorisation""" 
    43      
    44     def __init__(self, 
    45                  smWSDL, 
    46                  aaWSDL, 
    47                  userName=None, 
    48                  passPhrase=None, 
    49                  smPubKeyFilePath=None, 
    50                          clntPubKeyFilePath=None, 
    51                          clntPriKeyFilePath=None, 
    52                          clntPriKeyPwd=None, 
    53                          aaPubKey=None, 
    54                  org=None, 
    55                  bDebug=False): 
    56         """Omit username, passphrase and org if running from CGI""" 
    57          
    58         self.__aaWSDL = aaWSDL    
    59         self.__smWSDL = smWSDL    
    60         self.__userName = userName 
    61         self.__passPhrase = passPhrase 
    62         self.__smPubKeyFilePath = smPubKeyFilePath 
    63         self.__clntPubKeyFilePath = clntPubKeyFilePath 
    64         self.__clntPriKeyFilePath = clntPriKeyFilePath 
    65         self.__clntPriKeyPwd = clntPriKeyPwd 
    66         self.__aaPubKey = aaPubKey 
    67  
    68         self.__bDebug = bDebug 
    69  
    70         # Authenticating organisation 
    71         self.__org = org 
    72  
    73         # Flag taken from form radio button decides whether mapping is 
    74         # allowed or not and if so, should the user be prompted for which 
    75         # attribute certificate to submit 
    76         self.__authorisationMethod = None 
    77  
    78         self.__attCert = None 
    79          
    80          
     15from NDG.SecurityCGI import * 
     16 
     17 
     18class TestSecurityCGI(SecurityCGI): 
     19    """CGI interface test class for NDG Security""" 
     20 
     21 
    8122    #_________________________________________________________________________ 
    82     def cgi(self):         
    83         """Two stage process - login followed by authentication.  If 
    84         authentication fails re-call login.""" 
    85  
    86         # Use userName field to flag authentication call         
    87         form = cgi.FieldStorage() 
    88         bAuthorise = form.has_key("authorise") 
    89  
    90  
    91         #sys.stderr.write("Form keys: %s\n" % ', '.join(form.keys())) 
    92  
    93 #         if form.has_key("extTrustedHost"): 
    94 #             extTrustedHost = form["extTrustedHost"].value 
    95 #         else: 
    96 #             extTrustedHost = '' 
    97  
    98         if form.has_key("authorisationMethod"): 
    99             self.__authorisationMethod = form["authorisationMethod"].value 
    100  
    101  
    102         if form.has_key("addUser"): 
    103  
    104             # Register new account 
    105             if not form.has_key("userName") or not form["userName"].value: 
    106                 raise SecurityCGIError("No username set") 
    107              
    108             if not form.has_key("passPhrase") or not form["passPhrase"].value: 
    109                 raise SecurityCGIError("No pass-phrase set") 
    110              
    111             if not form.has_key("confirmPassPhrase") or \ 
    112                not form["confirmPassPhrase"].value: 
    113                 raise SecurityCGIError("No confirmation pass-phrase set") 
    114  
    115             if form["passPhrase"].value != form["confirmPassPhrase"].value: 
    116                 raise SecurityCGIError(\ 
    117                     "Pass-phrase and confirmation pass-phrase don't agree") 
    118                  
    119             self.__userName = form["userName"].value 
    120             self.__passPhrase = form["passPhrase"].value 
    121  
    122             self.addUser() 
    123              
    124         elif form.has_key("login") or not form.keys(): 
    125              
    126             # Login 
    127             print "Content-type: text/html" + os.linesep 
    128             self.showLogin(bAuthorise=bAuthorise, bodyTag=True) 
    129              
    130         elif form.has_key("authenticate"): 
    131  
    132             # Authentication 
    133             if form.has_key("userName") and form["userName"].value: 
    134                 self.__userName = form["userName"].value 
    135              
    136             if form.has_key("passPhrase") and form["passPhrase"].value: 
    137                 self.__passPhrase = form["passPhrase"].value 
    138                  
    139             if form.has_key("org") and form["org"].value: 
    140                 self.__org = form["org"].value 
    141  
    142             if bAuthorise: 
    143                                      
    144                 # Authorisation and authentication arguments were set 
    145                 # - Call authentication first 
    146                 cookie = self.authenticate(setCookie=False) 
    147  
    148                 # Call authorisation passing the session ID for authorise to 
    149                 # set the cookie 
    150                 self.authorise(cookie) 
    151  
    152             else: 
    153                 # Only the authentication flag was set - Call authentication 
    154                 # and set cookie 
    155                 self.authenticate() 
    156  
    157         elif bAuthorise: 
    158             self.authorise() 
    159  
    160         elif form.has_key("cookie"):            
    161             self.setCookie(form['cookie'].value) 
    162  
    163         elif form.has_key("attCert"): 
    164             self.showAttCert(attCert=form['attCert'].value) 
    165  
     23    def showLogin(self, returnURI=None, bAuthorise=False, **kwargs): 
     24        """Display initial NDG login form""" 
     25 
     26        if returnURI: 
     27            returnURIfield = \ 
     28             "<input type=hidden name=\"returnURI\" value=\"%s\">" % returnURI 
    16629        else: 
    167             raise SecurityCGIError(\ 
    168                             "None of the Form keys were recognised: %s" % \ 
    169                             ', '.join(form.keys())) 
    170  
    171  
    172     #_________________________________________________________________________ 
    173     def showLogin(self, 
    174                   bAuthorise=False, 
    175                   htmlTag=False, 
    176                   heading=None, 
    177                   bodyTag=False): 
    178         """Display initial NDG login form""" 
    179         if htmlTag: print "<html>" 
    180          
    181         if isinstance(heading, basestring): 
    182             print """<head> 
    183     <title>%s</title> 
    184     <style type=\"text/css\"> 
    185     <!-- 
    186         .al { 
    187         text-align: justify 
    188         } 
    189         a{ 
    190         text-decoration:none; 
    191         } 
    192         a:hover{ 
    193         color:#0000FF; 
    194         } 
    195         body { font-family: Verdana, sans-serif; font-size: 11} 
    196         table { font-family: Verdana, sans-serif; font-size: 11} 
    197     --> 
    198     </style> 
    199 </head>""" % heading 
    200  
    201  
    202         if bodyTag: print "<body>" 
     30            returnURIfield = '' 
     31 
    20332 
    20433        if bAuthorise: 
    205             authoriseArg = "<input type=hidden name=authorise value=\"1\">" 
     34            authoriseField = \ 
     35                "<input type=hidden name=\"authorise\" value=\"1\">" 
    20636        else: 
    207             authoriseArg = "" 
     37            authoriseField = "" 
    20838 
    20939 
    21040        # Set authorisation method default 
    211         authorisationMethodChk = { "allowMapping":              '', 
    212                                    "allowMappingWithPrompt" :   '', 
    213                                    "noMapping":                 ''} 
    214  
    215         if self.__authorisationMethod is None: 
     41        authorisationMethodChk = {  "allowMapping":              '', 
     42                                    "allowMappingWithPrompt" :   '', 
     43                                    "noMapping":                 ''} 
     44 
     45        if self._authorisationMethod is None: 
    21646            # Default to safest option for user 
    21747            authorisationMethodChk["allowMappingWithPrompt"] = ' checked' 
    21848        else: 
    219             authorisationMethodChk[self.__authorisationMethod] = ' checked' 
    220          
    221         print \ 
    222 """<script language="javascript"> 
     49            authorisationMethodChk[self._authorisationMethod] = ' checked' 
     50 
     51 
     52        print """Content-type: text/html 
     53 
     54<html> 
     55<head> 
     56<title>Gabriel Login (NDG Test)</title> 
     57<style type=\"text/css\"> 
    22358<!-- 
    224     function toggleLayer(layerId) 
    225     { 
    226         if (document.getElementById) 
    227         { 
    228             // Standard 
    229             var style = document.getElementById(layerId).style; 
    230         } 
    231         else if (document.all) 
    232         { 
    233             // Old msie versions 
    234             var style = document.all[whichLayer].style; 
    235         } 
    236         else if (document.layers) 
    237         { 
    238             // nn4 
    239             var style = document.layers[whichLayer].style; 
    240         } 
    241         style.visibility = style.visibility == "visible" ? "hidden":"visible"; 
    242     } 
    243 //--> 
    244 </script> 
    245 <h3>NERC Data Grid Site Login (Test)<BR clear=all></h3> 
    246 <hr> 
    247  
    248 <form action="./security.cgi" method="POST"> 
    249  
    250 <table bgcolor=#ADD8E6 cellspacing=0 border=0 cellpadding=5> 
    251 <tbody> 
    252 <tr><td>User Name:</td> <td><input type=text name=userName value=""> 
    253 </td></tr> 
    254 <tr> 
    255     <td>Password:</td> 
    256     <td><input type=password name=passPhrase></td> 
    257 </tr> 
    258 <tr> 
    259     <td colspan="2" align="right"> 
    260         <a href="javascript:toggleLayer('advSettings');">Advanced Settings</a> 
    261         <input type=submit value="Login"> 
    262     </td> 
    263 </tr> 
    264 <input type=hidden name=authenticate value="1"> 
    265 %s"""  % authoriseArg 
    266  
    267         print \ 
    268 """</tbody></table> 
    269 <br> 
    270 <div id="advSettings" style="position: relative; visibility: hidden;"> 
    271     <h4>Role Mapping for access to other trusted sites</h4> 
    272     <p>Your account has roles or <i>privileges</i> which determine what data you have access to.  If you access data at another NDG trusted site, these roles can be mapped to local roles at that site to help you gain access: 
    273     </p> 
     59.al { 
     60text-align: justify 
     61} 
     62a{ 
     63text-decoration:none; 
     64} 
     65a:hover{ 
     66color:#0000FF; 
     67} 
     68    body { font-family: Verdana, sans-serif; font-size: 11} 
     69    table { font-family: Verdana, sans-serif; font-size: 11} 
     70--> 
     71</style> 
     72</head> 
     73<body> 
     74    <script language="javascript"> 
     75        <!-- 
     76            function toggleLayer(layerId) 
     77            { 
     78                if (document.getElementById) 
     79                { 
     80                    // Standard 
     81                    var style = document.getElementById(layerId).style; 
     82                } 
     83                else if (document.all) 
     84                { 
     85                    // Old msie versions 
     86                    var style = document.all[whichLayer].style; 
     87                } 
     88                else if (document.layers) 
     89                { 
     90                    // nn4 
     91                    var style = document.layers[whichLayer].style; 
     92                } 
     93                style.visibility = style.visibility == "visible" ? 
     94"hidden":"visible";            } 
     95        //--> 
     96    </script> 
     97    <h3>Gabriel Login (NDG Test)<BR clear=all></h3> 
     98    <hr> 
     99 
     100    <form action="%s" method="POST"> 
     101 
    274102    <table bgcolor=#ADD8E6 cellspacing=0 border=0 cellpadding=5> 
    275103    <tbody> 
    276104    <tr> 
    277         <td> 
    278             <input type="radio" name="authorisationMethod" value="allowMapping"%s> 
    279         </td> 
    280         <td> 
    281             Allow my roles to be mapped to local roles at other NDG trusted sites. 
    282         </td> 
    283     </tr> 
    284     <tr> 
    285         <td> 
    286             <input type="radio" name="authorisationMethod" value="allowMappingWithPrompt"%s> 
    287         </td> 
    288         <td> 
    289             Allow my roles to be mapped, but prompt me so that I may choose which roles to map before gaining access. 
    290         </td> 
    291     <tr> 
    292         <td> 
    293             <input type="radio" name="authorisationMethod" value="noMapping"%s> 
    294         </td> 
    295         <td> 
    296             Don't allow mapping of my roles. 
    297         </td> 
    298     </tr> 
     105      <td>User Name:</td> 
     106      <td><input type=text name="userName" value=""></td> 
     107    </tr> 
     108    <tr> 
     109      <td>Password:</td> 
     110      <td><input type=password name="passPhrase"></td> 
     111    </tr> 
     112    <tr> 
     113      <td colspan="2" align="right"> 
     114        <a href="javascript:toggleLayer('advSettings');"> 
     115        Advanced Settings 
     116        </a> 
     117        <input type=submit value="Login"> 
     118      </td> 
     119    </tr> 
     120    <input type=hidden name="authenticate" value="1"> 
    299121    </tbody> 
    300122    </table> 
    301 </div> 
    302 </form> 
    303 """ % (authorisationMethodChk['allowMapping'], \ 
    304        authorisationMethodChk['allowMappingWithPrompt'], \ 
    305        authorisationMethodChk['noMapping']) 
    306  
    307         if bodyTag: print "</body>" 
    308         if htmlTag: print "</html>" 
    309  
    310     # end of showLogin() 
    311      
    312      
    313     #_________________________________________________________________________ 
    314     def addUser(self): 
    315         """Add a new NDG User account""" 
    316  
    317         if self.__userName is None: 
    318             raise SecurityCGIError("No username set") 
    319          
    320         if self.__passPhrase is None: 
    321             raise SecurityCGIError("No passphrase set") 
    322  
    323         if self.__bDebug: 
    324             traceFile = sys.stderr 
    325         else: 
    326             traceFile = None 
    327             
    328         try: 
    329             # Instantiate WS proxy and request connection 
    330             try: 
    331                 smClient = SessionClient( 
    332                         smWSDL=self.__smWSDL, 
    333                         smPubKeyFilePath=self.__smPubKeyFilePath, 
    334                                 clntPubKeyFilePath=self.__clntPubKeyFilePath, 
    335                                 clntPriKeyFilePath=self.__clntPriKeyFilePath, 
    336                         traceFile=traceFile) 
    337  
    338  
    339                 smClient.addUser(userName=self.__userName, 
    340                                  pPhrase=self.__passPhrase, 
    341                                  clntPriKeyPwd=self.__clntPriKeyPwd) 
    342             except Exception, e: 
    343                 raise SecurityCGIError("Session Client: " + str(e)) 
    344  
    345             print \ 
    346 """Content-type: text/html 
    347  
     123    %s 
     124    %s 
     125    </form> 
     126</body> 
     127</html>"""  % (self.scriptName, returnURIfield, authoriseField) 
     128 
     129        print \ 
     130"""    </tbody> 
     131    </table> 
     132    <br> 
     133    <div id="advSettings" style="position: relative; visibility: hidden;"> 
     134      <h4>Role Mapping for access to other trusted sites</h4> 
     135      <p>Your account has roles or <i>privileges</i> which determine what data 
     136you have access to.  If you access data at another NDG trusted site, these 
     137roles can be mapped to local roles at that site to help you gain access: 
     138      </p> 
     139    <table bgcolor=#ADD8E6 cellspacing=0 border=0 cellpadding=5> 
     140    <tbody> 
     141      <tr> 
     142        <td><input type="radio" name="authorisationMethod" 
     143value="allowMapping"%s> 
     144        </td> 
     145        <td> 
     146        Allow my roles to be mapped to local roles at other NDG trusted sites. 
     147        </td> 
     148      </tr> 
     149      <tr> 
     150        <td> 
     151          <input type="radio" name="authorisationMethod" 
     152value="allowMappingWithPrompt"%s> 
     153        </td> 
     154        <td> 
     155            Allow my roles to be mapped, but prompt me so that I may choose 
     156which roles to map before gaining access. 
     157        </td> 
     158        <tr> 
     159        <td> 
     160          <input type="radio" name="authorisationMethod" value="noMapping"%s> 
     161        </td> 
     162        <td> 
     163          Don't allow mapping of my roles. 
     164        </td> 
     165        </tr> 
     166      </tbody> 
     167      </table> 
     168    </div> 
     169    </form> 
     170</body> 
     171</html>""" % (authorisationMethodChk['allowMapping'], \ 
     172              authorisationMethodChk['allowMappingWithPrompt'], \ 
     173              authorisationMethodChk['noMapping']) 
     174 
     175        # end of showLogin() 
     176 
     177 
     178    def showHomeSiteSelect(self, **kwargs): 
     179 
     180        if not self.trustedHostInfo: 
     181            self.getTrustedHostInfo() 
     182 
     183        print """Content-type: text/html 
     184 
     185<html> 
    348186<head> 
    349     <title>NDG User Registration (Test)</title> 
    350     <style type="text/css"> 
     187    <title>Select site to retrieve credentials</title> 
     188    <style type=\"text/css\"> 
    351189    <!-- 
    352         .al { 
    353         text-align: justify 
    354         } 
    355         a{ 
    356         text-decoration:none; 
    357         } 
    358         a:hover{ 
    359         color:#0000FF; 
    360         } 
     190    .al { 
     191    text-align: justify 
     192    } 
     193    a{ 
     194    text-decoration:none; 
     195    } 
     196    a:hover{ 
     197    color:#0000FF; 
     198    } 
    361199        body { font-family: Verdana, sans-serif; font-size: 11} 
    362200        table { font-family: Verdana, sans-serif; font-size: 11} 
     
    365203</head> 
    366204<body> 
    367     <p>New user %s registered</p> 
    368 </body>""" % self.__userName 
    369          
    370         except Exception, e: 
    371             # Re-display login screen 
    372             print \ 
    373 """Content-type: text/html 
    374  
     205    <form action="%s" method="POST"> 
     206    <table bgcolor=#ADD8E6 cellspacing=0 border=0 cellpadding=5> 
     207    <tbody> 
     208    <tr> 
     209      <td> 
     210        <select name="requestURI"> 
     211          <option value="">Select your home site...""" % self.scriptName 
     212 
     213        for hostname, info in self.trustedHostInfo.items(): 
     214            print "<option value=\"%s\">%s" % (info['loginURI'], hostname) 
     215 
     216        print \ 
     217"""     </select> 
     218      </td> 
     219      <td align="right"> 
     220        <input type=submit value="Go"> 
     221      </td> 
     222    </tr> 
     223    </tbody> 
     224    </table> 
     225    </form> 
     226</body> 
     227</html>""" 
     228 
     229        # end of showHomeSiteSelect() 
     230 
     231 
     232    #_________________________________________________________________________ 
     233    def showCredsReceived(self, 
     234                              sessCookie, 
     235                                                  pageTitle='', 
     236                                                  hdrTxt='', 
     237                                                  bodyTxt=''): 
     238        """Called from receiveCredsResponse() once a cookie has been created. 
     239        Makes a page to set the cookie and display to the user that they have 
     240        been authenticated.  Derived class should override this method as 
     241        required""" 
     242        print """Content-type: text/html 
     243%s 
     244 
     245<html> 
    375246<head> 
    376     <title>NDG User Registration (Test)</title> 
    377     <style type="text/css"> 
     247<title>NDG Authentication</title> 
     248    <style type=\"text/css\"> 
    378249    <!-- 
    379         .al { 
    380         text-align: justify 
    381         } 
    382         a{ 
    383         text-decoration:none; 
    384         } 
    385         a:hover{ 
    386         color:#0000FF; 
    387         } 
     250    .al { 
     251    text-align: justify 
     252    } 
     253    a{ 
     254    text-decoration:none; 
     255    } 
     256    a:hover{ 
     257    color:#0000FF; 
     258    } 
    388259        body { font-family: Verdana, sans-serif; font-size: 11} 
    389260        table { font-family: Verdana, sans-serif; font-size: 11} 
     
    391262    </style> 
    392263</head> 
    393  
    394264<body> 
    395     <p>Registration failed for new user account %s: %s</p>""" % \ 
    396             (self.__userName, e) 
    397              
    398             raise SecurityCGIError("User registration failed: %s" % e) 
    399      
    400      
    401     #_________________________________________________________________________ 
    402     def authenticate(self, setCookie=True, bAuthorise=False): 
    403         """Authenticate username and passphrase input from preceeding login 
    404         form 
    405  
    406         bAuthorise: set to True so that if an error occurs, login will be 
    407                     recalled followed by authorisation""" 
    408  
    409         if self.__bDebug: 
    410             traceFile = sys.stderr 
    411         else: 
    412             traceFile = None 
    413  
    414              
    415         try: 
    416             if self.__userName is None: 
    417                 raise SecurityCGIError("no username set") 
    418  
    419             if self.__passPhrase is None: 
    420                 raise SecurityCGIError("no pass-phrase input") 
    421              
    422             # Instantiate WS proxy and request connection 
    423             try: 
    424                 smClient = SessionClient( 
    425                         smWSDL=self.__smWSDL, 
    426                         smPubKeyFilePath=self.__smPubKeyFilePath, 
    427                                 clntPubKeyFilePath=self.__clntPubKeyFilePath, 
    428                                 clntPriKeyFilePath=self.__clntPriKeyFilePath, 
    429                         traceFile=traceFile) 
    430  
    431                 sessCookie = smClient.connect(userName=self.__userName, 
    432                                               pPhrase=self.__passPhrase, 
    433                                               clntPriKeyPwd=self.__clntPriKeyPwd) 
    434             except Exception, e: 
    435                 # Socket error returns tuple - reformat to just give msg 
    436                 raise SecurityCGIError("Session client: " + str(e)) 
    437  
    438  
    439             if setCookie: 
    440                 print \ 
    441 """Content-type: text/html 
    442 %s 
    443  
    444 <head> 
    445     <title>NDG User Authentication (Test)</title> 
    446     <style type="text/css"> 
    447     <!-- 
    448         .al { 
    449         text-align: justify 
    450         } 
    451         a{ 
    452         text-decoration:none; 
    453         } 
    454         a:hover{ 
    455         color:#0000FF; 
    456         } 
    457         body { font-family: Verdana, sans-serif; font-size: 11} 
    458         table { font-family: Verdana, sans-serif; font-size: 11} 
    459     --> 
    460     </style> 
    461 </head> 
    462  
    463 <body> 
    464     <p>User %s authenticated</p> 
    465     <p>Cookie is: %s</p> 
    466 </body>""" % (sessCookie, self.__userName, sessCookie) 
    467             return sessCookie 
    468          
    469         except Exception, e: 
    470             # Re-display login screen 
    471             if self.__userName is None: 
    472                 msgFmt = '' 
    473             else: 
    474                 msgFmt = " for user '%s'" % self.__userName 
    475                  
    476             print \ 
    477 """Content-type: text/html 
    478  
    479 <head> 
    480     <title>NDG User Authentication (Test)</title> 
    481     <style type="text/css"> 
    482     <!-- 
    483         .al { 
    484         text-align: justify 
    485         } 
    486         a{ 
    487         text-decoration:none; 
    488         } 
    489         a:hover{ 
    490         color:#0000FF; 
    491         } 
    492         body { font-family: Verdana, sans-serif; font-size: 11} 
    493         table { font-family: Verdana, sans-serif; font-size: 11} 
    494     --> 
    495     </style> 
    496 </head> 
    497  
    498 <body>"""             
    499             self.showLogin(bAuthorise=bAuthorise) 
    500             print \ 
    501 """<script>alert("Login error%s: %s")</script>  
    502 </body>""" % (msgFmt, e) 
    503              
    504             raise SecurityCGIError("Login failed: %s" % e) 
    505  
    506  
    507     #_________________________________________________________________________ 
    508     def authorise(self, cookie=None, reqRole=None): 
    509         """Contact Attribute Authority to get Attribute Certificate for data 
    510         access 
    511  
    512         cookie:     cookie containing session ID 
    513         reqRole:    required role to get authorisation - default to NERC for 
    514                     testing""" 
    515  
    516         if self.__bDebug: 
    517             traceFile = sys.stderr 
    518         else: 
    519             traceFile = None 
    520  
    521  
    522         extAttCertList = None 
    523         bSetCookie = False 
    524          
    525                                 
    526         try: 
    527             # Check for session ID input 
    528             if isinstance(cookie, basestring): 
    529                 bSetCookie = True 
    530  
    531             elif 'HTTP_COOKIE' not in os.environ: 
    532                 # Check for session ID set in existing cookie 
    533                      
    534                 # Re-display login screen 
    535                 print "Content-type: text/html" + os.linesep                     
    536                 self.showLogin(bAuthorise=True, 
    537                                bodyTag=True, 
    538                                heading="NDG User Authorisation (Test)") 
    539  
    540                 return 
    541             else: 
    542                 cookie = os.environ['HTTP_COOKIE'] 
    543                  
    544                  
    545             # Get session ID from existing cookie 
    546             cookieObj = SimpleCookie(cookie) 
    547             if "NDG-ID1" not in cookieObj: 
    548                 raise SecurityCGIError(\ 
    549                             'Expecting "NDG-ID1" ID for session cookie') 
    550                               
    551             if "NDG-ID2" not in cookieObj: 
    552                 raise SecurityCGIError(\ 
    553                             'Expecting "NDG-ID2" ID for session cookie')  
    554  
    555  
    556             if self.__authorisationMethod == 'allowMapping': 
    557                 bMapFromTrustedHosts = True 
    558                 bRtnExtAttCertList = True 
    559  
    560             elif self.__authorisationMethod == 'allowMappingWithPrompt': 
    561                 bMapFromTrustedHosts = False 
    562                 bRtnExtAttCertList = True 
    563             else: 
    564                 bMapFromTrustedHosts = False 
    565                 bRtnExtAttCertList = False 
    566  
    567  
    568             # Instantiate WS proxy and request authorisation 
    569             try: 
    570                 smClient = SessionClient( 
    571                             smWSDL=self.__smWSDL, 
    572                             smPubKeyFilePath=self.__smPubKeyFilePath, 
    573                                     clntPubKeyFilePath=self.__clntPubKeyFilePath, 
    574                                     clntPriKeyFilePath=self.__clntPriKeyFilePath, 
    575                             traceFile=traceFile) 
    576  
    577                 resp = smClient.reqAuthorisation(sessCookie=cookieObj, 
    578                                     aaWSDL=self.__aaWSDL, 
    579                                                     aaPubKey=self.__aaPubKey, 
    580                                     reqRole=reqRole, 
    581                                     rtnExtAttCertList=bRtnExtAttCertList, 
    582                                     clntPriKeyPwd=self.__clntPriKeyPwd) 
    583             except Exception, e: 
    584                 # Socket error returns tuple - reformat to just give msg 
    585                 raise SecurityCGIError("Session client: " + str(e)) 
    586  
    587             if resp['statCode'] == 'AccessGranted': 
    588                 # Convert from unicode 
    589                 self.__attCert = str(resp['attCert']) 
    590              
    591             elif resp['statCode'] == 'AccessDenied': 
    592                  
    593                 if 'extAttCertList' not in resp or not resp['extAttCertList']: 
    594                     raise SecurityCGIError(str(resp['errMsg'])) 
    595  
    596             elif resp['statCode'] == 'AccessError': 
    597                 raise SecurityCGIError(str(resp['errMsg'])) 
    598  
    599  
    600             # Handle access denied/granted 
    601             if bSetCookie: 
    602                 cookieTxt = cookie + os.linesep 
    603             else: 
    604                 cookieTxt = '' 
    605  
    606             print \ 
    607 """Content-type: text/html 
    608 %s 
    609  
    610 <head> 
    611     <Title>NDG User Authorisation (Test)</Title> 
    612     <script language="JavaScript"> 
    613         <!-- 
    614         function ndgDataOpenWindow(theURL, winName, features) 
    615         { //v2.0 
    616             window.open(theURL, winName, features); 
    617         } 
    618         //--> 
    619   </script> 
    620     <style type="text/css"> 
    621     <!-- 
    622         .al { 
    623         text-align: justify 
    624         } 
    625         a{ 
    626         text-decoration:none; 
    627         } 
    628         a:hover{ 
    629         color:#0000FF; 
    630         } 
    631         body { font-family: Verdana, sans-serif; font-size: 11} 
    632         table { font-family: Verdana, sans-serif; font-size: 11} 
    633     --> 
    634     </style> 
    635 </head> 
    636  
    637 <body>""" % cookieTxt 
    638  
    639             if self.__attCert: 
    640  
    641                 # Get data using certificate obtained 
    642                 print "<p>User authorised</p>" 
    643  
    644                 print "<p>Attribute Certificate: <br>%s</p>" % \ 
    645                        re.sub("<", "&lt;", re.sub(">", "&gt;", self.__attCert)) 
    646  
    647             elif 'extAttCertList' in resp: 
    648                 # Display available certificates from other AAs in a table 
    649                 self.showExtAttCertSelect(resp['extAttCertList']) 
    650                  
    651             print "</body>" 
    652  
    653         except Exception, e: 
    654                         
    655             # Re-display login screen 
    656             print \ 
    657 """Content-type: text/html 
    658  
    659 <head> 
    660     <title>NDG User Authorisation (Test)</title> 
    661     <style type="text/css"> 
    662     <!-- 
    663         .al { 
    664         text-align: justify 
    665         } 
    666         a{ 
    667         text-decoration:none; 
    668         } 
    669         a:hover{ 
    670         color:#0000FF; 
    671         } 
    672         body { font-family: Verdana, sans-serif; font-size: 11} 
    673         table { font-family: Verdana, sans-serif; font-size: 11} 
    674     --> 
    675     </style> 
    676 </head> 
    677  
    678 <body>""" 
    679              
    680             self.showLogin(bAuthorise=True) 
    681             print \ 
    682 """<script>alert("Authorisation failed: %s")</script> 
    683 </body>""" % e 
    684              
    685             raise SecurityCGIError("Authorisation failed: %s" % e) 
    686      
    687  
    688     def showAttCert(self, attCert=None): 
    689         """Make a page to display Attribute Certificate""" 
    690         if attCert is not None: 
    691             self.__attCert = attCert 
    692  
    693         if self.__attCert is None: 
    694             print \ 
    695 """Content-type: text/html 
    696  
    697 <head> 
    698     <title>NDG User Authorisation (Test)</title> 
    699     <style type="text/css"> 
    700     <!-- 
    701         .al { 
    702         text-align: justify 
    703         } 
    704         a{ 
    705         text-decoration:none; 
    706         } 
    707         a:hover{ 
    708         color:#0000FF; 
    709         } 
    710         body { font-family: Verdana, sans-serif; font-size: 11} 
    711         table { font-family: Verdana, sans-serif; font-size: 11} 
    712     --> 
    713     </style> 
    714 </head> 
    715  
    716 <body> 
    717     <p>No Attribute Certificate set</p> 
    718 </body>""" 
    719             return 
    720          
    721         print \ 
    722 """Content-type: text/xml 
    723  
    724 %s""" % self.__attCert 
    725              
    726  
    727     #_________________________________________________________________________ 
    728     def showExtAttCertSelect(self, 
    729                              extAttCertList, 
    730                              htmlTag=False, 
    731                              heading=None, 
    732                              bodyTag=False): 
    733         """Display table for selection of external attribute certificates for 
    734         mapping""" 
    735         if htmlTag: print "<html>" 
    736          
    737         if isinstance(heading, basestring): 
    738             print """<head> 
    739     <title>%s</title> 
    740     <style type="text/css"> 
    741     <!-- 
    742         .al { 
    743         text-align: justify 
    744         } 
    745         a{ 
    746         text-decoration:none; 
    747         } 
    748         a:hover{ 
    749         color:#0000FF; 
    750         } 
    751         body { font-family: Verdana, sans-serif; font-size: 11} 
    752         table { font-family: Verdana, sans-serif; font-size: 11} 
    753     --> 
    754     </style> 
    755 </head>""" % heading 
    756  
    757         sys.stderr.write("extAttCertList: \n\n%s\n" % extAttCertList) 
    758          
    759         # Display title and table first row 
    760         # 
    761         # Form contains hidden fields so that on submit, authorisation is 
    762         # called to get authorisation via a mapped certificate 
    763         print \ 
    764 """<h2>NDG Data Access</h2> 
    765 <hr style="width: 100%; height: 2px;"><br> 
    766 <p>Select a certificate to allow access to data:</p> 
    767 <form action="./security.cgi" method="post"> 
    768     <input type=hidden name=authorise value="1"> 
    769     <input type=hidden name=authorisationMethod value="allowMapping"> 
    770     <table style="width: 100%;" border="0" cellpadding="10" 
    771     cellspacing="1"> 
    772         <tbody> 
    773         <tr bgcolor="#d5d5de"> 
    774             <td style="text-align: left; vertical-align: top;"> 
    775                 <br> 
    776             </td> 
    777             <td style="width: 10px; text-align: left; vertical-align: top;"> 
    778                 <span style="font-weight: bold;">Issuer</span> 
    779             </td> 
    780             <td style="text-align: left; vertical-align: top;"> 
    781                 <span style="font-weight: bold;">Available Roles</span> 
    782             </td> 
    783         </tr>""" 
    784  
    785         # Display available certificates - one in each row 
    786         chkTxt = ['' for i in range(len(extAttCertList))] 
    787         chkTxt[0] = ' checked' 
    788          
    789         for sCert in extAttCertList: 
    790  
    791             cert = AttCertParse(sCert) 
    792  
    793             # Nb. hidden field authorisationMethod set to allowMapping so that 
    794             # authorisation request can be made again but this time with the 
    795             # s 
    796             print """ 
    797         <tr bgcolor="#e2e2e2"> 
    798             <td style="vertical-align: top;"> 
    799                 <input type="radio" name="extTrustedHost" 
    800                 value="%s"%s><br> 
    801             </td> 
    802             <td style="width: 20px;" valign="top"> 
    803                 %s<br> 
    804             </td> 
    805             <td valign="top" width="80%%"> 
    806                 %s<br> 
    807             </td> 
    808         </tr> 
    809 """ % (cert['issuerName'], 
    810        chkTxt.pop(), 
    811        cert['issuerName'], 
    812        ', '.join(cert.getRoles())) 
    813  
    814         print \ 
    815 """        <tr bgcolor="#d5d5de"> 
    816             <td colspan="3" align="right"> 
    817                 <input type=submit value="   OK   "> 
    818                 <input type=button value="Cancel" 
    819                  onClick="javascript:window.close();"> 
    820             </td> 
    821         </tr> 
    822         </tbody> 
    823     </table> 
    824 </form> 
    825 """ 
    826          
    827         if bodyTag: print "</body>" 
    828         if htmlTag: print "</html>" 
    829  
    830     # end of showExtAttCertSelect() 
    831  
    832  
    833  
    834     #_________________________________________________________________________ 
    835     def setCookie(self, cookie): 
    836         """Set a page with input cookie""" 
    837         print "Content-type: text/html" 
    838         print cookie 
    839  
    840  
    841  
    842          
     265    New cookie set from credentials transfered from other domain 
     266</body> 
     267</html>""" % sessCookie.output() 
     268 
     269 
    843270#_____________________________________________________________________________ 
    844271if __name__ == "__main__": 
    845272 
    846     smWSDL = "http://.../sessionMgr.wsdl" 
    847     aaWSDL = "http://.../attAuthority.wsdl" 
    848     try: 
    849         aaPubKey=open("...cert.pem").read() 
    850  
    851     except IOError, (errNo, errMsg): 
    852         raise Exception("Making temporary file for Attribute " + \ 
    853                                   "Authority public key: %s" % errMsg) 
    854     except Exception, e: 
    855         raise Exception("Making temporary file for Attribute " + \ 
    856                                   "Authority public key: %s" % str(e)) 
    857  
    858  
    859     smPubKeyFilePath = "...cert.pem" 
    860     clntPubKeyFilePath = "...-cert.pem" 
    861     clntPriKeyFilePath = "...-key.pem" 
    862  
    863  
    864  
    865     # Instantiate and call CGI 
    866     security = SecurityCGI(smWSDL, 
    867                            aaWSDL, 
    868                            smPubKeyFilePath=smPubKeyFilePath, 
    869                                    clntPubKeyFilePath=clntPubKeyFilePath, 
    870                                    clntPriKeyFilePath=clntPriKeyFilePath, 
    871                                    aaPubKey=aaPubKey, 
    872                                    bDebug=False) 
    873     security.cgi() 
     273    smWSDL = "http://gabriel.bnsc.rl.ac.uk/sessionMgr.wsdl" 
     274    aaWSDL = 'http://gabriel.bnsc.rl.ac.uk/attAuthority.wsdl' 
     275 
     276    smPubKeyFilePath = "/usr/local/NDG/conf/certs/gabriel-sm-cert.pem" 
     277    aaPubKeyFilePath = "/usr/local/NDG/conf/certs/gabriel-aa-cert.pem" 
     278 
     279    clntPubKeyFilePath = "../certs/GabrielCGI-cert.pem" 
     280    clntPriKeyFilePath = "../certs/GabrielCGI-key.pem" 
     281 
     282    securityCGI = TestSecurityCGI(smWSDL, 
     283                                  aaWSDL, 
     284                                                  scriptName=os.path.basename(__file__), 
     285                                  smPubKeyFilePath=smPubKeyFilePath, 
     286                                  aaPubKeyFilePath=aaPubKeyFilePath, 
     287                                  clntPubKeyFilePath=clntPubKeyFilePath, 
     288                                  clntPriKeyFilePath=clntPriKeyFilePath) 
     289    securityCGI() 
Note: See TracChangeset for help on using the changeset viewer.