removed another bunch of references to geni
[sfa.git] / sfa / trust / auth.py
1 #
2 # SfaAPI authentication 
3 #
4 ### $Id$
5 ### $URL$
6 #
7
8 import time
9
10 from sfa.trust.credential import Credential
11 from sfa.trust.trustedroot import TrustedRootList
12 from sfa.trust.rights import RightList
13 from sfa.util.faults import *
14 from sfa.trust.hierarchy import Hierarchy
15 from sfa.util.config import *
16 from sfa.util.namespace import *
17 from sfa.trust.gid import GID
18 from sfa.util.sfaticket import *
19
20 class Auth:
21     """
22     Credential based authentication
23     """
24
25     def __init__(self, peer_cert = None, config = None ):
26         self.peer_cert = peer_cert
27         self.hierarchy = Hierarchy()
28         if not config:
29             self.config = Config()
30         self.trusted_cert_list = TrustedRootList(self.config.get_trustedroots_dir()).get_list()
31
32
33     def check(self, cred, operation):
34         """
35         Check the credential against the peer cert (callerGID included 
36         in the credential matches the caller that is connected to the 
37         HTTPS connection, check if the credential was signed by a 
38         trusted cert and check if the credential is allowd to perform 
39         the specified operation.    
40         """
41         self.client_cred = Credential(string = cred)
42         self.client_gid = self.client_cred.get_gid_caller()
43         self.object_gid = self.client_cred.get_gid_object()
44         
45         # make sure the client_gid is not blank
46         if not self.client_gid:
47             raise MissingCallerGID(self.client_cred.get_subject())
48        
49         # validate the client cert if it exists
50         if self.peer_cert:
51             self.verifyPeerCert(self.peer_cert, self.client_gid)                   
52
53         # make sure the client is allowed to perform the operation
54         if operation:
55             if not self.client_cred.can_perform(operation):
56                 raise InsufficientRights(operation)
57
58         if self.trusted_cert_list:
59             self.client_cred.verify_chain(self.trusted_cert_list)
60             if self.client_gid:
61                 self.client_gid.verify_chain(self.trusted_cert_list)
62             if self.object_gid:
63                 self.object_gid.verify_chain(self.trusted_cert_list)
64         else:
65            raise MissingTrustedRoots(self.config.get_trustedroots_dir())
66
67         return True
68
69     def check_ticket(self, ticket):
70         """
71         Check if the tickt was signed by a trusted cert
72         """
73         if self.trusted_cert_list:
74             client_ticket = SfaTicket(string=ticket)
75             client_ticket.verify_chain(self.trusted_cert_list)
76         else:
77            raise MissingTrustedRoots(self.config.get_trustedroots_dir())
78
79         return True 
80
81     def verifyPeerCert(self, cert, gid):
82         # make sure the client_gid matches client's certificate
83         if not cert:
84             peer_cert = self.peer_cert
85         else:
86             peer_cert = cert
87
88         if not gid:
89             peer_gid = self.client_gid
90         else:
91             peer_gid = gid
92         if not peer_cert.is_pubkey(peer_gid.get_pubkey()):
93             raise ConnectionKeyGIDMismatch(peer_gid.get_subject())            
94
95     def verifyGidRequestHash(self, gid, hash, arglist):
96         key = gid.get_pubkey()
97         if not key.verify_string(str(arglist), hash):
98             raise BadRequestHash(hash)
99
100     def verifyCredRequestHash(self, cred, hash, arglist):
101         gid = cred.get_gid_caller()
102         self.verifyGidRequestHash(gid, hash, arglist)
103
104     def validateGid(self, gid):
105         if self.trusted_cert_list:
106             gid.verify_chain(self.trusted_cert_list)
107
108     def validateCred(self, cred):
109         if self.trusted_cert_list:
110             cred.verify_chain(self.trusted_cert_list)
111             caller_gid = cred.get_gid_caller()
112             object_gid = cred.get_gid_object()
113             if caller_gid:
114                 caller_gid.verify_chain(self.trusted_cert_list)
115             if object_gid:
116                 object_gid.verify_chain(self.trusted_cert_list)
117
118     def authenticateGid(self, gidStr, argList, requestHash=None):
119         gid = GID(string = gidStr)
120         self.validateGid(gid)
121         # request_hash is optional
122         if requestHash:
123             self.verifyGidRequestHash(gid, requestHash, argList)
124         return gid
125
126     def authenticateCred(self, credStr, argList, requestHash=None):
127         cred = Credential(string = credStr)
128         self.validateCred(cred)
129         # request hash is optional
130         if requestHash:
131             self.verifyCredRequestHash(cred, requestHash, argList)
132         return cred
133
134     def authenticateCert(self, certStr, requestHash):
135         cert = Certificate(string=certStr)
136         self.validateCert(self, cert)   
137
138     def gidNoop(self, gidStr, value, requestHash):
139         self.authenticateGid(gidStr, [gidStr, value], requestHash)
140         return value
141
142     def credNoop(self, credStr, value, requestHash):
143         self.authenticateCred(credStr, [credStr, value], requestHash)
144         return value
145
146     def verify_cred_is_me(self, credential):
147         is_me = False 
148         cred = Credential(string=credential)
149         caller_gid = cred.get_gid_caller()
150         caller_hrn = caller_gid.get_hrn()
151         if caller_hrn != self.config.SFA_INTERFACE_HRN:
152             raise SfaPermissionDenied(self.config.SFA_INTEFACE_HRN)
153
154         return   
155         
156     def get_auth_info(self, auth_hrn):
157         """
158         Given an authority name, return the information for that authority.
159         This is basically a stub that calls the hierarchy module.
160         
161         @param auth_hrn human readable name of authority  
162         """
163
164         return self.hierarchy.get_auth_info(auth_hrn)
165
166
167     def veriry_auth_belongs_to_me(self, name):
168         """
169         Verify that an authority belongs to our hierarchy. 
170         This is basically left up to the implementation of the hierarchy
171         module. If the specified name does not belong, ane exception is 
172         thrown indicating the caller should contact someone else.
173
174         @param auth_name human readable name of authority
175         """
176
177         # get auth info will throw an exception if the authority doesnt exist
178         self.get_auth_info(name)
179
180
181     def verify_object_belongs_to_me(self, name):
182         """
183         Verify that an object belongs to our hierarchy. By extension,
184         this implies that the authority that owns the object belongs
185         to our hierarchy. If it does not an exception is thrown.
186     
187         @param name human readable name of object        
188         """
189         auth_name = self.get_authority(name)
190         if not auth_name:
191             auth_name = name 
192         if name == self.config.SFA_INTERFACE_HRN:
193             return
194         self.verify_auth_belongs_to_me(auth_name) 
195              
196     def verify_auth_belongs_to_me(self, name):
197         # get auth info will throw an exception if the authority doesnt exist
198         self.get_auth_info(name) 
199
200
201     def verify_object_permission(self, name):
202         """
203         Verify that the object gid that was specified in the credential
204         allows permission to the object 'name'. This is done by a simple
205         prefix test. For example, an object_gid for plc.arizona would 
206         match the objects plc.arizona.slice1 and plc.arizona.
207     
208         @param name human readable name to test  
209         """
210         object_hrn = self.object_gid.get_hrn()
211         if object_hrn == name:
212             return
213         if name.startswith(object_hrn + "."):
214             return
215         #if name.startswith(get_authority(name)):
216             #return
217     
218         raise PermissionError(name)
219
220     def determine_user_rights(self, caller_hrn, record):
221         """
222         Given a user credential and a record, determine what set of rights the
223         user should have to that record.
224         
225         This is intended to replace determine_rights() and
226         verify_cancreate_credential()
227         """
228
229         rl = RightList()
230         type = record['type']
231
232         if type=="slice":
233             researchers = record.get("researcher", [])
234             pis = record.get("PI", [])
235             if (caller_hrn in researchers + pis):
236                 rl.add("refresh")
237                 rl.add("embed")
238                 rl.add("bind")
239                 rl.add("control")
240                 rl.add("info")
241
242         elif type == "authority":
243             pis = record.get("PI", [])
244             operators = record.get("operator", [])
245             if (caller_hrn == self.config.SFA_INTERFACE_HRN):
246                 rl.add("authority,sa,ma",)
247             if (caller_hrn in pis):
248                 rl.add("authority,sa")
249             if (caller_hrn in operators):
250                 rl.add("authority,ma")
251
252         elif type == "user":
253             rl.add("refresh")
254             rl.add("resolve")
255             rl.add("info")
256
257         elif type == "node":
258             rl.add("operator")
259
260         return rl
261
262     def verify_cancreate_credential(self, src_cred, record):
263         """
264         Verify that a user can retrive a particular type of credential.
265         For slices, the user must be on the researcher list. For SA and
266         MA the user must be on the pi and operator lists respectively
267         """
268
269         type = record.get_type()
270         cred_object_hrn = src_cred.get_gid_object().get_hrn()
271         if cred_object_hrn in [self.config.SFA_REGISTRY_ROOT_AUTH]:
272             return
273         if type=="slice":
274             researchers = record.get("researcher", [])
275             if not (cred_object_hrn in researchers):
276                 raise PermissionError(cred_object_hrn + " is not in researcher list for " + record.get_name())
277         elif type == "sa":
278             pis = record.get("pi", [])
279             if not (cred_object_hrn in pis):
280                 raise PermissionError(cred_object_hrn + " is not in pi list for " + record.get_name())
281         elif type == "ma":
282             operators = record.get("operator", [])
283             if not (cred_object_hrn in operators):
284                 raise PermissionError(cred_object_hrn + " is not in operator list for " + record.get_name())
285
286     def get_authority(self, hrn):
287         return get_authority(hrn)