1 | from Utilities import wrapGetText |
---|
2 | from NDG.SecurityClient import * |
---|
3 | |
---|
4 | class AccessControl: |
---|
5 | |
---|
6 | ''' Handle the access control metadata and provide three attributes of the |
---|
7 | access control: exists (existence), status (modified elsewhere for whether |
---|
8 | user can access data), and html (a message about the constraints). ''' |
---|
9 | |
---|
10 | def __init__(self,e): |
---|
11 | if e is None: |
---|
12 | self.status=1 |
---|
13 | self.exist=0 |
---|
14 | self.html='' |
---|
15 | else: |
---|
16 | #for now assume everything with a simplecondition is deny |
---|
17 | self.html=wrapGetText(e,'dgSecurityCondition/conditionExplanationText') |
---|
18 | sc='dgSecurityCondition/simpleCondition/' |
---|
19 | self.SimpleCondition=(wrapGetText(e,sc+'attrauthRole'), |
---|
20 | wrapGetText(e,sc+'dgAttributeAuthority')) |
---|
21 | if self.SimpleCondition==('',''): self.SimpleCondition=None |
---|
22 | self.status=0 |
---|
23 | self.exist=1 |
---|
24 | |
---|
25 | class gateway2NDGsession: |
---|
26 | |
---|
27 | ''' This class provides a gateway to the NDG session manager and methods upon it ''' |
---|
28 | |
---|
29 | def __init__(self,url,config,desiredAA=None,cookie=None,cmdLine=None): |
---|
30 | |
---|
31 | ''' The use case is that we attempt to establish a gateway to an |
---|
32 | existing NDG session. If it exists, fine, if it doesn't, then we |
---|
33 | don't do anything, but wait til a check call before attempting |
---|
34 | to establish a connection ... that way we can prompt with an appropriate |
---|
35 | set of hosts. |
---|
36 | |
---|
37 | If an NDG cookie exists, or we have it on the commandline, we use it |
---|
38 | by reEstablishing to the existing session. |
---|
39 | ''' |
---|
40 | |
---|
41 | #First we have to see if the ndgsecurity info is in the cooki |
---|
42 | self.url=url |
---|
43 | self.connected=0 |
---|
44 | self.config=config |
---|
45 | if cookie is not None: |
---|
46 | if self.__SecCookie(): |
---|
47 | self.__reEstablish(cookie=cookie) |
---|
48 | return |
---|
49 | if cmdLine is not None: |
---|
50 | self.__reEstablish(cmdLine=cmdLine) |
---|
51 | |
---|
52 | |
---|
53 | def check(self, parsedSimpleCondition): |
---|
54 | ''' can the credentials in the wallet support access to the resource requiring |
---|
55 | the role at wsdlAA - parsedSimpleCondition is a tuple - (role, wsdlAA) ''' |
---|
56 | #connect using cookie |
---|
57 | |
---|
58 | #first make sure we've got real conditions, if not, deny ... |
---|
59 | if parsedSimpleCondition is None: return 0 |
---|
60 | |
---|
61 | #if not connected, get connected |
---|
62 | if not self.connected: return self.__Establish(parsedSimpleCondition) |
---|
63 | |
---|
64 | resp = self.smClient.reqAuthorisation(sessCookie=cookieObj, |
---|
65 | aaWSDL=wsdlAA, |
---|
66 | aaPubKey=None, # the session client can get that from the WSDL |
---|
67 | reqRole=role, |
---|
68 | rtnExtAttCertList=None, #auto select role map for now |
---|
69 | clntPriKeyPwd=None # not using encrypted yet |
---|
70 | ) |
---|
71 | return 'AccessGranted' |
---|
72 | |
---|
73 | def __SecCookie(self): |
---|
74 | ''' Check the current cookie and see if it contains security information, but |
---|
75 | we (the CGI) don't need to parse it - that's done in the NDG session client''' |
---|
76 | if self.cookie is None: |
---|
77 | return 0 |
---|
78 | else: |
---|
79 | try: |
---|
80 | for i in ('NDG-ID1','NDG-ID2'): |
---|
81 | if i not in self.cookie: return 0 |
---|
82 | except: |
---|
83 | return 0 |
---|
84 | return 1 |
---|
85 | |
---|
86 | |
---|
87 | def __Establish(self,parsedSimpleCondition): |
---|
88 | ''' Establish an NDG security session. We work out who to login |
---|
89 | with by getting the list of trusted hosts from the parsedSimpleCondition |
---|
90 | (which is just a tuple - role, attribute authority). This results in |
---|
91 | a redirect to a user chosen host, after which we get back a URI with |
---|
92 | the cookie posted as a (hidden) uri argument ''' |
---|
93 | |
---|
94 | AA=AttAuthorityClient(aaWSDL=parsedSimpleCondition[1]) |
---|
95 | trustedHostDict=AA.getTrustedHostInfo(role=parsedSimpleCondition[0]) |
---|
96 | loginHostList=[] |
---|
97 | for key in trustedHostDict: |
---|
98 | loginHostList.append((key,trustedHostDict[key]['loginURI'])) |
---|
99 | |
---|
100 | return self.__showSiteList(loginHostList) |
---|
101 | |
---|
102 | def __reEstablish(self,cookie=None,cmdLine=None): |
---|
103 | ''' bind to the existing WSDL ''' |
---|
104 | |
---|
105 | if cmdLine is not None: |
---|
106 | sessID,encrSessMgrWDLURI=cmdLine |
---|
107 | |
---|
108 | self.__loadKeys() |
---|
109 | try: |
---|
110 | #set up session client |
---|
111 | # (all these keys to do message level encryption while talking to server, |
---|
112 | # see __loadKeys for more details) |
---|
113 | self.smClient = SessionClient( |
---|
114 | sessCookie=cookie, |
---|
115 | encrSessMgrWSDLuri=WSDLuri, |
---|
116 | sessID=sessID, |
---|
117 | smPubKeyFilePath=self.__localSessionManagerPublicKey, |
---|
118 | clntPubKeyFilePath=self.__thisCGIpublicKey, |
---|
119 | clntPriKeyFilePath=self.__thisCGIprivateKey, |
---|
120 | traceFile=traceFile) |
---|
121 | self.connected=1 |
---|
122 | except Exception, e: |
---|
123 | # Socket error returns tuple - reformat to just give msg |
---|
124 | #raise SecurityCGIError("Session client: " + str(e)) |
---|
125 | pass # for now we don't have the libraries or code attached |
---|
126 | |
---|
127 | def __loadKeys(self): |
---|
128 | ''' Load security keys ''' |
---|
129 | |
---|
130 | # We (potentially) need the public and private keys of this cgi script |
---|
131 | # and the public key of the session client if our communication goes |
---|
132 | # out over the public network and we want to deploy message |
---|
133 | # level encryption. |
---|
134 | |
---|
135 | #However, for the first installation, we will assume both the CGI and |
---|
136 | #the session manager are running behind the same firewall. |
---|
137 | |
---|
138 | self.__thisCGIpublicKey=None |
---|
139 | self.__thisCGIprivateKey=None |
---|
140 | |
---|
141 | #these are the things I need to talk to my local session manager |
---|
142 | self.__localSessionManagerPublicKey=None |
---|
143 | self.__localSessionManagerProxyWSDL=self.config.get('Security','localSM',None) |
---|
144 | |
---|
145 | #we need to call out to smWSDL to get their public key as a first step? |
---|
146 | #self.__remoteSessionManagerPublicKey=self.__getKey(smWSDL) |
---|
147 | |
---|
148 | return |
---|
149 | |
---|
150 | def __getPublicKey(self,smWSDL): |
---|
151 | ''' Given the WSDL address of a session manager object, get the public key associated |
---|
152 | with it ''' |
---|
153 | return None |
---|
154 | |
---|
155 | def __showSiteList(self,loginList,heading=''): |
---|
156 | '''Show the user a list of trusted hosts, and redirect to one of them ''' |
---|
157 | html='''<p> Access to resource [<b>%s</b>] requires credentials, please login ...' |
---|
158 | <hr> |
---|
159 | <form action="https://glue.badc.rl.ac.uk/cgi-bin/security.py" method="POST"> |
---|
160 | <table bgcolor=#ADD8E6 cellspacing=0 border=0 cellpadding=5> |
---|
161 | <tbody><tr> |
---|
162 | <td><select name="requestURI"> |
---|
163 | <option value="">Select your home site...'''%self.url |
---|
164 | for i,j in loginList: |
---|
165 | html+='<option value="%s">%s'%(j,i) |
---|
166 | html+='''</select></td> |
---|
167 | <td align="right"><input type=submit value="Login"></td> |
---|
168 | </tr></tbody> |
---|
169 | </table> |
---|
170 | <input type="hidden" name="returnURI" value="%s"> |
---|
171 | </form> |
---|
172 | </body> |
---|
173 | </html>'''%self.url |
---|
174 | return html |
---|
175 | |
---|
176 | |
---|
177 | |
---|