Changeset 1337 for TI12-security
- Timestamp:
- 27/07/06 14:39:50 (13 years ago)
- Location:
- TI12-security/trunk/python
- Files:
-
- 2 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
TI12-security/trunk/python/NDG/SecurityCGI.py
r1331 r1337 1 1 #!/usr/bin/env python 2 2 3 """NDG Security CGI services3 """NDG Security CGI Interface between Service Providers and Identiy Providers 4 4 5 5 NERC Data Grid Project … … 32 32 pass 33 33 34 34 35 # Default style for HTML pages. This can easily be overriden using keyword 36 # settings or overriding methods in a derived class. 37 __defStyle = """ <style type=\"text/css\"> 38 <!-- 39 .al { 40 text-align: justify 41 } 42 a{ 43 text-decoration:none; 44 } 45 a:hover{ 46 color:#0000FF; 47 } 48 body { font-family: Verdana, sans-serif; font-size: 11} 49 table { font-family: Verdana, sans-serif; font-size: 11} 50 --> 51 </style>""" 52 53 35 54 class _SecurityCGI(cgi.FieldStorage): 36 """CGI interface base class for NDG Security 37 38 Terms used throughout: 39 Service Provider - where user is accessing resources 40 Identity Provider - where user's credentials are held or they login 55 """CGI Service Provider - Identity Provider interface base class for NDG 56 Security 57 58 Service Provider - serves NDG resources over http 59 Identity Provider - holds NDG user accounts and supports authentication 60 over http 41 61 """ 42 62 … … 49 69 #_________________________________________________________________________ 50 70 def __init__(self, 51 smWSDL,52 smPubKeyFilePath=None,53 71 clntPubKeyFilePath=None, 54 72 clntPriKeyFilePath=None, … … 57 75 wsDebug=False, 58 76 **cgiFieldStorageKwArgs): 59 """smWSDL: URI For Session Manager WSDL used for user 60 authentication 61 wsDebug: print output from WS transactions to stderr""" 62 63 self.smWSDL = smWSDL 64 self.smClnt = None 65 66 self.smPubKeyFilePath = smPubKeyFilePath 77 """clntPubKeyFilePath: file path to client public key. The CGI 78 script must have access to a public/private 79 key to enable encryption of return traffic 80 from NDG security WSs. IF THIS KEYWORD IS 81 NOT SET, RETURN TRAFFIC IS UNENCRYPTED. 82 clntPriKeyFilePath: file path to client private key. 83 clntPriKeyPwd: password protecting the private key. If no 84 password is set, omit this keyword. 85 wsDebug: print output from WS transactions to stderr 86 for debu purposes. 87 """ 67 88 68 89 self.clntPubKeyFilePath = clntPubKeyFilePath … … 76 97 self.attCert = None 77 98 99 # Read fields so that self becomes a dictionary of the fields 78 100 cgi.FieldStorage.__init__(self, **cgiFieldStorageKwArgs) 79 101 … … 167 189 if not self.smClnt: 168 190 self.smClnt = SessionClient(\ 169 smWSDL =self.smWSDL,191 smWSDLuri=self.smWSDLuri, 170 192 smPubKeyFilePath=self.smPubKeyFilePath, 171 193 clntPubKeyFilePath=self.clntPubKeyFilePath, … … 174 196 175 197 authzResp = self.smClnt.reqAuthorisation(sessCookie=sessCookie, 176 aaWSDL =self.aaWSDL,198 aaWSDLuri=self.aaWSDLuri, 177 199 aaPubKey=self.aaPubKey, 178 200 reqRole=reqRole, … … 273 295 #_____________________________________________________________________________ 274 296 class ServiceProviderSecurityCGI(_SecurityCGI): 275 297 """CGI interface for a Service Provider requesting user credentials 298 299 It enables the user to select an Identity Provider login page from a list 300 of trusted hosts, re-directs the user browser to the login and then can 301 process credentials passed back from the IdP to enable a new NDG security 302 cookie to be set in the Service Provider target domain. 303 """ 304 276 305 #_________________________________________________________________________ 277 306 def __init__(self, 278 smWSDL, 279 aaWSDL, 307 aaWSDLuri, 308 aaPubKeyFilePath=None, 309 smWSDLuri=None, 280 310 smPubKeyFilePath=None, 281 aaPubKeyFilePath=None,282 311 trustedHostInfo=None, 283 312 cookieLifetimeHrs=8, 284 313 **securityCGIKwArgs): 285 """smWSDL: URI For Session Manager WSDL used for user 286 authentication 287 aaWSDL: URI for Attribute Authority WSDL used to get a 314 """aaWSDLuri: URI for Attribute Authority WSDL used to get a 288 315 list of login URI for trusted hosts 316 smWSDLuri: URI For Session Manager WSDL used for querying 317 user session wallet for Attribute Certificates. 318 Only needed for _getAttCert calls 319 aaPubKeyFilePath: file path to Attribute Authority public key. 320 If not set, the client will make a WS call for 321 it. 289 322 trustedHostInfo: dictionary of URIs for trusted hosts indexed by 290 323 hostname 291 cookieLifetimeHrs: cookie lifetime in hours 324 cookieLifetimeHrs: cookie lifetime in hours for new cookie set in 325 Service Provider target domain. 292 326 wsDebug: print output from WS transactions to stderr""" 293 327 294 self.smWSDL = smWSDL 328 self.aaWSDLuri = aaWSDLuri 329 self.aaClnt = None 330 331 self.aaPubKeyFilePath = aaPubKeyFilePath 332 333 self.smWSDLuri = smWSDLuri 295 334 self.smClnt = None 296 335 297 self.aaWSDL = aaWSDL298 self.aaClnt = None299 300 336 self.smPubKeyFilePath = smPubKeyFilePath 301 self.aaPubKeyFilePath = aaPubKeyFilePath 337 302 338 303 339 self.trustedHostInfo = trustedHostInfo … … 312 348 self.attCert = None 313 349 314 super(self.__class__, self).__init__( self,**securityCGIKwArgs)350 super(self.__class__, self).__init__(**securityCGIKwArgs) 315 351 316 352 … … 328 364 encodedExpiry='expires' in self and self['expires'].value or None 329 365 330 self._receiveCredsResponse(encodedExpiry=encodedExpiry, 331 **kwargs) 366 self._receiveCredsResponse(encodedExpiry=encodedExpiry, **kwargs) 332 367 333 368 … … 339 374 htmlTag=False, 340 375 hdrTag=False, 341 hdrTxt= '',376 hdrTxt=__defStyle, 342 377 bodyTag=False, 343 378 pageTitle=""): … … 360 395 361 396 if hdrTag: 362 if not hdrTxt:363 hdrTxt = """ <style type=\"text/css\">364 <!--365 .al {366 text-align: justify367 }368 a{369 text-decoration:none;370 }371 a:hover{372 color:#0000FF;373 }374 body { font-family: Verdana, sans-serif; font-size: 11}375 table { font-family: Verdana, sans-serif; font-size: 11}376 -->377 </style>"""378 379 397 print """<head> 380 398 … … 387 405 print "<body>\n" 388 406 389 print """ 407 # Form containing droplist for the trusted hosts 408 print """ 390 409 <form action="%s" method="POST"> 391 410 <table bgcolor=#ADD8E6 cellspacing=0 border=0 cellpadding=5> … … 396 415 <option value="">Select your home site...""" % self.scriptName 397 416 398 399 417 for hostname, info in self.trustedHostInfo.items(): 418 print "<option value=\"%s\">%s" % (info['loginURI'], hostname) 400 419 401 420 print \ 402 421 """ </select> 403 422 </td> … … 420 439 421 440 #_________________________________________________________________________ 422 def showCredsReceived(self, sessCookie): 441 def showCredsReceived(self, 442 sessCookie, 443 pageTitle='Credentials Received', 444 hdrTxt=__defStyle, 445 bodyText='NDG Security session cookie set'): 423 446 """Called from _receiveCredsResponse() once a cookie has been created. 424 447 Makes a page to set the cookie and display to the user that they have 425 448 been authenticated. Derived class should override this method as 426 449 required""" 450 427 451 print """Content-type: text/html" 428 452 %s … … 430 454 <html> 431 455 <head> 432 <title>Credentials Received</title> 456 <title>%s</title> 457 %s 433 458 </head> 434 459 <body> 435 Credentials Received460 %s 436 461 </body> 437 </html>""" % sessCookie.output()462 </html>""" % (sessCookie.output(), pageTitle, hdrTxt, bodyTxt) 438 463 439 464 … … 445 470 try: 446 471 if not self.aaClnt: 447 self.aaClnt = AttAuthorityClient(aaWSDL =self.aaWSDL,472 self.aaClnt = AttAuthorityClient(aaWSDLuri=self.aaWSDLuri, 448 473 aaPubKeyFilePath=self.aaPubKeyFilePath, 449 474 clntPubKeyFilePath=self.clntPubKeyFilePath, … … 535 560 #_____________________________________________________________________________ 536 561 class IdentityProviderSecurityCGI(_SecurityCGI): 537 538 #_________________________________________________________________________ 539 def __init__(self, smWSDL, **securityCGIKwArgs): 540 """smWSDL: URI For Session Manager WSDL used for user 541 authentication""" 542 543 self.smWSDL = smWSDL 562 """CGI for an NDG Identity provider. The IdP serves user credentials 563 back to a requesting Service Provider. 564 565 An NDG Service Provider redirects the user's browser to an IdP login 566 script using this class. If the user is already logged in, then a 567 security cookie will be present and it's content returned to the SP by 568 http redirect. If no cookie is present the user must login first but then 569 similarly, the content of the new cookie is returned to the SP. The SP 570 can them set a new security cookie it's target domain.""" 571 572 # _processCredsRequest must check that the returnURI given uses HTTPS 573 __httpsSpecifier = "https:" 574 575 576 #_________________________________________________________________________ 577 def __init__(self, 578 smWSDLuri, 579 smPubKeyFilePath=None, 580 userName=None, 581 passPhrase=None, 582 **securityCGIKwArgs): 583 """smWSDLuri: URI For Session Manager WSDL used for user 584 authentication 585 smPubKeyFilePath: file path for Session Manager public key. If 586 not set it will be retrieved using a 587 Session Manager WS call. 588 userName: normally set from user input to form in 589 showLogin() 590 passPhrase: ditto""" 591 592 self.smWSDLuri = smWSDLuri 544 593 self.smClnt = None 594 595 self.smPubKeyFilePath = smPubKeyFilePath 545 596 546 597 self.userName = userName 547 598 self.passPhrase = passPhrase 548 549 self.smPubKeyFilePath = smPubKeyFilePath550 599 551 super(self.__class__, self).__init__( self,**securityCGIKwArgs)600 super(self.__class__, self).__init__(**securityCGIKwArgs) 552 601 553 602 … … 555 604 def processFields(self, **kwargs): 556 605 """Call appropriate actions according to the fields set""" 557 558 606 559 607 bAuthorise = "authorise" in self 560 608 … … 598 646 sessCookie=None, 599 647 **returnCredsResponseKwArgs): 600 """Receive request from remote site for credentials. Process and601 return via a redirect"""648 """Receive request from a Service Provider for credentials. Process 649 and return via a redirect""" 602 650 603 651 if returnURI is None: 604 652 returnURI = self['returnURI'].value 605 653 654 606 655 # Check for cookie in environment 607 656 if sessCookie is None and 'HTTP_COOKIE' in os.environ: … … 609 658 # Get session ID from existing cookie 610 659 sessCookie = SimpleCookie(os.environ['HTTP_COOKIE']) 660 bValidSessCookie = UserSession.isValidSecurityCookie(sessCookie) 661 662 else: 663 bValidSessCookie = False 664 665 666 # Check that the returnURI is over https, if not credentials would be 667 # returned to the service provider in clear text and could be snooped 668 # The exception to this is where returnURI and IdP URI are in the 669 # same domain. In this case credentials would not be passed between 670 # SP and IdP URIs anyway 671 if returnURI[0:6] != self.__httpsSpecifier and \ 672 not bValidSessCookie or \ 673 sessCookie[UserSession.cookieTags[0]]['domain'] not in returnURI: 674 raise SecurityCGIError, "Specified returnURI must use HTTPS" 675 611 676 612 677 # Check for NDG cookie 613 if sessCookie and UserSession.isValidSecurityCookie(sessCookie):678 if sessCookie and bValidSessCookie: 614 679 615 680 # Return cookie to requestor 616 self. returnCredsResponse(sessCookie,617 returnURI,618 **returnCredsResponseKwArgs)681 self._returnCredsResponse(sessCookie, 682 returnURI, 683 **returnCredsResponseKwArgs) 619 684 620 685 else: … … 628 693 #_________________________________________________________________________ 629 694 def _returnCredsResponse(self, 630 sessCookie,631 returnURI=None,632 pageTitle='',633 hdrTxt='',634 delayTime=0,635 redirectMsg='',636 setCookie=False):695 sessCookie, 696 returnURI=None, 697 pageTitle='', 698 hdrTxt='', 699 delayTime=0, 700 redirectMsg='', 701 setCookie=False): 637 702 """User's Identity Provider returns credentials to requestor via a 638 703 HTTP redirect … … 644 709 page will be displayed in this interval 645 710 redirectMsg: Message to put on redirect page. Can be plain text or 646 formatted HTML""" 711 formatted HTML 712 setCookie: Set to True to set the cookie in the IdP's target 713 domain. This could be used in the case where the user 714 has just logged in but the session cookie has not been 715 set yet.""" 647 716 648 717 if returnURI is None: … … 654 723 cookieTxt = '' 655 724 725 656 726 # Check to see if the returnURI is in the same domain - if so there's 657 727 # no need to return any credentials in the redirect 658 728 cookieDomain = sessCookie[UserSession.cookieTags[0]]['domain'] 659 729 if cookieDomain and cookieDomain in returnURI: 730 credArgs = '' 731 732 else: 733 # returnURI is in a different domain - return the credentials 734 # Add credentials to URI but loop through so as to not have to 735 # refer to the tag names directly. Tag names are abstracted 736 # behind the UserSession interface 737 sessCookieArgs = '&'.join(["%s=%s" % (tag, sessCookie[tag].value)\ 738 for tag in UserSession.cookieTags]) 739 740 b64encExpiry = base64.urlsafe_b64encode(\ 741 sessCookie[UserSession.cookieTags[0]]['expires']) 742 743 # Nb. Allow for case where return URI already includes some args 744 credArgs = "%s%s&expires=%s" % \ 745 ('?' in returnURI and '&' or '?', sessCookieArgs, b64encExpiry) 746 747 660 748 print """Content-type: text/html 661 749 %s … … 664 752 <title>%s</title> 665 753 <meta http-equiv="REFRESH" 666 content="%d; url=%s ">754 content="%d; url=%s%s"> 667 755 %s 668 756 </head> … … 670 758 %s 671 759 </body> 672 </html>""" % ( cookieTxt, 673 pageTitle, 674 delayTime, 675 returnURI, 676 hdrTxt, 677 redirectMsg) 678 679 else: 680 # returnURI is in a different domain - return the credentials 681 # 682 # Allow for case where return URI already includes some args 683 if '?' in returnURI: 684 argSeparator = '&' 685 else: 686 argSeparator = '?' 687 688 689 print """Content-type: text/html 690 %s 691 <html> 692 <head> 693 <title>%s</title> 694 <meta http-equiv="REFRESH" 695 content="%d; url=%s%sNDG-ID1=%s&NDG-ID2=%s&expires=%s"> 696 %s 697 </head> 698 <body> 699 %s 700 </body> 701 </html>""" % ( cookieTxt, 702 pageTitle, 703 delayTime, 704 returnURI, 705 argSeparator, 706 sessCookie['NDG-ID1'].value, 707 sessCookie['NDG-ID2'].value, 708 base64.urlsafe_b64encode(sessCookie['NDG-ID1']['expires']), 709 hdrTxt, 710 redirectMsg) 760 </html>""" % (cookieTxt, 761 pageTitle, 762 delayTime, 763 returnURI, 764 credArgs, 765 hdrTxt, 766 redirectMsg) 711 767 712 768 … … 742 798 try: 743 799 if not self.smClnt: 744 self.smClnt = SessionClient(smWSDL =self.smWSDL,800 self.smClnt = SessionClient(smWSDLuri=self.smWSDLuri, 745 801 smPubKeyFilePath=self.smPubKeyFilePath, 746 802 clntPubKeyFilePath=self.clntPubKeyFilePath, … … 767 823 htmlTag=True, 768 824 pageTitle='', 769 hdrTxt= '',825 hdrTxt=__defStyle, 770 826 headTag=True, 771 827 bodyTag=True, … … 778 834 779 835 if headTag: 780 if not hdrTxt:781 hdrTxt = """ <style type=\"text/css\">782 <!--783 .al {784 text-align: justify785 }786 a{787 text-decoration:none;788 }789 a:hover{790 color:#0000FF;791 }792 body { font-family: Verdana, sans-serif; font-size: 11}793 table { font-family: Verdana, sans-serif; font-size: 11}794 -->795 </style>"""796 797 836 print """<head> 798 837 <title>%s</title> … … 898 937 <tr> 899 938 <td> 900 <input type="radio" name="authorisationMethod" value="%s"%s> </td> 939 <input type="radio" name="authorisationMethod" value="%s"%s> 940 </td> 901 941 <td> 902 942 Allow my roles to be mapped, but prompt me so that I may choose -
TI12-security/trunk/python/README
r1308 r1337 1 NDG Security 0.72 Post-Alpha Release (version development 24/07/06)2 ___________________________________________ ________________________1 NDG Security Post-Alpha Development Version 2 ___________________________________________ 3 3 4 4 To install: -
TI12-security/trunk/python/setup.py
r1308 r1337 18 18 { 19 19 'name': 'NDG-Security', 20 'version': ' 0.72',20 'version': 'Dev-PostAlpha', 21 21 'description': 'NERC DataGrid Security Utilities', 22 22 'author': 'P J Kershaw',
Note: See TracChangeset
for help on using the changeset viewer.