added verify_cred_is_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         self.get_auth_info(name)
100
101
102     def verify_object_belongs_to_me(self, name):
103         """
104         Verify that an object belongs to our hierarchy. By extension,
105         this implies that the authority that owns the object belongs
106         to our hierarchy. If it does not an exception is thrown.
107     
108         @param name human readable name of object        
109         """
110         auth_name = self.get_authority(name)
111         if not auth_name or name == self.config.SFA_INTERFACE_HRN:
112             # the root authority belongs to the registry by default?
113             # TODO: is this true?
114             return
115         self.verify_auth_belongs_to_me(auth_name) 
116              
117     def verify_auth_belongs_to_me(self, name):
118         # get auth info will throw an exception if the authority doesnt exist
119         self.get_auth_info(name) 
120
121
122     def verify_object_permission(self, name):
123         """
124         Verify that the object gid that was specified in the credential
125         allows permission to the object 'name'. This is done by a simple
126         prefix test. For example, an object_gid for plc.arizona would 
127         match the objects plc.arizona.slice1 and plc.arizona.
128     
129         @param name human readable name to test  
130         """
131         object_hrn = self.object_gid.get_hrn()
132         if object_hrn == name:
133             return
134         if name.startswith(object_hrn + "."):
135             return
136         #if name.startswith(get_authority(name)):
137             #return
138     
139         raise PermissionError(name)
140
141     def determine_user_rights(self, src_cred, record):
142         """
143         Given a user credential and a record, determine what set of rights the
144         user should have to that record.
145
146         Src_cred can be None when obtaining a user credential, but should be
147         set to a valid user credential when obtaining a slice or authority
148         credential.
149
150         This is intended to replace determine_rights() and
151         verify_cancreate_credential()
152         """
153
154         type = record['type']
155         if src_cred:
156             cred_object_hrn = src_cred.get_gid_object().get_hrn()
157         else:
158             # supplying src_cred==None is only valid when obtaining user
159             # credentials.
160             #assert(type == "user")
161             
162             cred_object_hrn = None
163
164         rl = RightList()
165
166         if type=="slice":
167             researchers = record.get("researcher", [])
168             if (cred_object_hrn in researchers):
169                 rl.add("refresh")
170                 rl.add("embed")
171                 rl.add("bind")
172                 rl.add("control")
173                 rl.add("info")
174
175         elif type == "authority":
176             pis = record.get("pi", [])
177             operators = record.get("operator", [])
178             rl.add("authority,sa,ma")
179             if (cred_object_hrn in pis):
180                 rl.add("sa")
181             if (cred_object_hrn in operators):
182                 rl.add("ma")
183
184         elif type == "user":
185             rl.add("refresh")
186             rl.add("resolve")
187             rl.add("info")
188
189         return rl
190
191     def verify_cancreate_credential(self, src_cred, record):
192         """
193         Verify that a user can retrive a particular type of credential.
194         For slices, the user must be on the researcher list. For SA and
195         MA the user must be on the pi and operator lists respectively
196         """
197
198         type = record.get_type()
199         cred_object_hrn = src_cred.get_gid_object().get_hrn()
200         if cred_object_hrn in [self.config.SFA_REGISTRY_ROOT_AUTH]:
201             return
202         if type=="slice":
203             researchers = record.get("researcher", [])
204             if not (cred_object_hrn in researchers):
205                 raise PermissionError(cred_object_hrn + " is not in researcher list for " + record.get_name())
206         elif type == "sa":
207             pis = record.get("pi", [])
208             if not (cred_object_hrn in pis):
209                 raise PermissionError(cred_object_hrn + " is not in pi list for " + record.get_name())
210         elif type == "ma":
211             operators = record.get("operator", [])
212             if not (cred_object_hrn in operators):
213                 raise PermissionError(cred_object_hrn + " is not in operator list for " + record.get_name())
214
215     def get_authority(self, hrn):
216         return get_authority(hrn)