fix bug in verify object belongs to me
[sfa.git] / sfa / trust / auth.py
1 #
2 # GeniAPI 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.genitable import GeniTable
16 from sfa.util.config import *
17 from sfa.util.misc import *
18
19 class Auth:
20     """
21     Credential based authentication
22     """
23
24     def __init__(self, peer_cert = None, config = None ):
25         self.peer_cert = peer_cert
26         self.hierarchy = Hierarchy()
27         self.trusted_cert_list = TrustedRootList().get_list() 
28         if not config:
29             self.config = Config() 
30     
31
32     def check(self, cred, operation):
33         """
34         Check the credential against the peer cert (callerGID included 
35         in the credential matches the caller that is connected to the 
36         HTTPS connection, check if the credential was signed by a 
37         trusted cert and check if the credential is allowd to perform 
38         the specified operation.    
39         """
40         self.client_cred = Credential(string = cred)
41         self.client_gid = self.client_cred.get_gid_caller()
42         self.object_gid = self.client_cred.get_gid_object()
43         
44         # make sure the client_gid is not blank
45         if not self.client_gid:
46             raise MissingCallerGID(self.client_cred.get_subject())
47
48         # make sure the client_gid matches client's certificate
49         peer_cert = self.peer_cert
50         if not peer_cert.is_pubkey(self.client_gid.get_pubkey()):
51             raise ConnectionKeyGIDMismatch(self.client_gid.get_subject())
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
65         return True
66
67
68     def verify_cred_is_me(self, credential):
69         is_me = False 
70         cred = Credential(string=credential)
71         caller_gid = cred.get_gid_caller()
72         caller_hrn = caller_gid.get_hrn()
73         if caller_hrn != self.config.SFA_INTERFACE_HRN:
74             raise GeniPermissionError(self.config.SFA_INTEFACE_HRN)
75
76         return   
77         
78     def get_auth_info(self, auth_hrn):
79         """
80         Given an authority name, return the information for that authority.
81         This is basically a stub that calls the hierarchy module.
82         
83         @param auth_hrn human readable name of authority  
84         """
85
86         return self.hierarchy.get_auth_info(auth_hrn)
87
88
89     def veriry_auth_belongs_to_me(self, name):
90         """
91         Verify that an authority belongs to our hierarchy. 
92         This is basically left up to the implementation of the hierarchy
93         module. If the specified name does not belong, ane exception is 
94         thrown indicating the caller should contact someone else.
95
96         @param auth_name human readable name of authority
97         """
98
99         # get auth info will throw an exception if the authority doesnt exist
100         self.get_auth_info(name)
101
102
103     def verify_object_belongs_to_me(self, name):
104         """
105         Verify that an object belongs to our hierarchy. By extension,
106         this implies that the authority that owns the object belongs
107         to our hierarchy. If it does not an exception is thrown.
108     
109         @param name human readable name of object        
110         """
111         auth_name = self.get_authority(name)
112         if not auth_name:
113             auth_name = name 
114         if name == self.config.SFA_INTERFACE_HRN:
115             return
116         self.verify_auth_belongs_to_me(auth_name) 
117              
118     def verify_auth_belongs_to_me(self, name):
119         # get auth info will throw an exception if the authority doesnt exist
120         self.get_auth_info(name) 
121
122
123     def verify_object_permission(self, name):
124         """
125         Verify that the object gid that was specified in the credential
126         allows permission to the object 'name'. This is done by a simple
127         prefix test. For example, an object_gid for plc.arizona would 
128         match the objects plc.arizona.slice1 and plc.arizona.
129     
130         @param name human readable name to test  
131         """
132         object_hrn = self.object_gid.get_hrn()
133         if object_hrn == name:
134             return
135         if name.startswith(object_hrn + "."):
136             return
137         #if name.startswith(get_authority(name)):
138             #return
139     
140         raise PermissionError(name)
141
142     def determine_user_rights(self, src_cred, record):
143         """
144         Given a user credential and a record, determine what set of rights the
145         user should have to that record.
146
147         Src_cred can be None when obtaining a user credential, but should be
148         set to a valid user credential when obtaining a slice or authority
149         credential.
150
151         This is intended to replace determine_rights() and
152         verify_cancreate_credential()
153         """
154
155         type = record['type']
156         if src_cred:
157             cred_object_hrn = src_cred.get_gid_object().get_hrn()
158         else:
159             # supplying src_cred==None is only valid when obtaining user
160             # credentials.
161             #assert(type == "user")
162             
163             cred_object_hrn = None
164
165         rl = RightList()
166
167         if type=="slice":
168             researchers = record.get("researcher", [])
169             if (cred_object_hrn in researchers):
170                 rl.add("refresh")
171                 rl.add("embed")
172                 rl.add("bind")
173                 rl.add("control")
174                 rl.add("info")
175
176         elif type == "authority":
177             pis = record.get("pi", [])
178             operators = record.get("operator", [])
179             rl.add("authority,sa,ma")
180             if (cred_object_hrn in pis):
181                 rl.add("sa")
182             if (cred_object_hrn in operators):
183                 rl.add("ma")
184
185         elif type == "user":
186             rl.add("refresh")
187             rl.add("resolve")
188             rl.add("info")
189
190         return rl
191
192     def verify_cancreate_credential(self, src_cred, record):
193         """
194         Verify that a user can retrive a particular type of credential.
195         For slices, the user must be on the researcher list. For SA and
196         MA the user must be on the pi and operator lists respectively
197         """
198
199         type = record.get_type()
200         cred_object_hrn = src_cred.get_gid_object().get_hrn()
201         if cred_object_hrn in [self.config.SFA_REGISTRY_ROOT_AUTH]:
202             return
203         if type=="slice":
204             researchers = record.get("researcher", [])
205             if not (cred_object_hrn in researchers):
206                 raise PermissionError(cred_object_hrn + " is not in researcher list for " + record.get_name())
207         elif type == "sa":
208             pis = record.get("pi", [])
209             if not (cred_object_hrn in pis):
210                 raise PermissionError(cred_object_hrn + " is not in pi list for " + record.get_name())
211         elif type == "ma":
212             operators = record.get("operator", [])
213             if not (cred_object_hrn in operators):
214                 raise PermissionError(cred_object_hrn + " is not in operator list for " + record.get_name())
215
216     def get_authority(self, hrn):
217         return get_authority(hrn)