use self.get_auth_info
[sfa.git] / geni / util / auth.py
1 #
2 # GeniAPI authentication 
3 #
4 ### $Id$
5 ### $URL$
6 #
7
8 import time
9
10 from geni.trust.credential import Credential
11 from geni.trust.trustedroot import TrustedRootList
12 from geni.trust.rights import RightList
13 from geni.util.faults import *
14 from geni.util.hierarchy import Hierarchy
15 from geni.util.genitable import *
16 from geni.util.config import *
17 from geni.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 get_auth_info(self, auth_hrn):
69         """
70         Given an authority name, return the information for that authority.
71         This is basically a stub that calls the hierarchy module.
72         
73         @param auth_hrn human readable name of authority  
74         """
75
76         return self.hierarchy.get_auth_info(auth_hrn)
77
78
79     def get_auth_table(self, auth_name):
80         """
81         Given an authority name, return the database table for that authority.
82         If the databse table does not exist, then one will be automatically
83         created.
84
85         @param auth_name human readable name of authority
86         """
87         auth_info = self.get_auth_info(auth_name)
88         table = GeniTable(hrn=auth_name,
89                           cninfo=auth_info.get_dbinfo())
90         # if the table doesn't exist, then it means we haven't put any records
91         # into this authority yet.
92
93         if not table.exists():
94             print >> log, "Registry: creating table for authority", auth_name
95             table.create()
96     
97         return table
98
99     def veriry_auth_belongs_to_me(self, name):
100         """
101         Verify that an authority belongs to our hierarchy. 
102         This is basically left up to the implementation of the hierarchy
103         module. If the specified name does not belong, ane exception is 
104         thrown indicating the caller should contact someone else.
105
106         @param auth_name human readable name of authority
107         """
108
109         self.get_auth_info(name)
110
111
112     def verify_object_belongs_to_me(self, name):
113         """
114         Verify that an object belongs to our hierarchy. By extension,
115         this implies that the authority that owns the object belongs
116         to our hierarchy. If it does not an exception is thrown.
117     
118         @param name human readable name of object        
119         """
120         auth_name = self.get_authority(name)
121         if not auth_name:
122             # the root authority belongs to the registry by default?
123             # TODO: is this true?
124             return
125         self.verify_auth_belongs_to_me(auth_name) 
126              
127     def verify_auth_belongs_to_me(self, name):
128         # get auth info will throw an exception if the authority doesnt exist
129         self.get_auth_info(name) 
130
131
132     def verify_object_permission(self, name):
133         """
134         Verify that the object gid that was specified in the credential
135         allows permission to the object 'name'. This is done by a simple
136         prefix test. For example, an object_gid for plc.arizona would 
137         match the objects plc.arizona.slice1 and plc.arizona.
138     
139         @param name human readable name to test  
140         """
141         object_hrn = self.object_gid.get_hrn()
142         if object_hrn == name:
143             return
144         if name.startswith(object_hrn + "."):
145             return
146         if name.startswith(get_authority(name)):
147             return
148     
149         raise PermissionError(name)
150
151     def determine_user_rights(self, src_cred, record):
152         """
153         Given a user credential and a record, determine what set of rights the
154         user should have to that record.
155
156         Src_cred can be None when obtaining a user credential, but should be
157         set to a valid user credential when obtaining a slice or authority
158         credential.
159
160         This is intended to replace determine_rights() and
161         verify_cancreate_credential()
162         """
163
164         type = record.get_type()
165         if src_cred:
166             cred_object_hrn = src_cred.get_gid_object().get_hrn()
167         else:
168             # supplying src_cred==None is only valid when obtaining user
169             # credentials.
170             #assert(type == "user")
171             
172             cred_object_hrn = None
173
174         rl = RightList()
175
176         if type=="slice":
177             researchers = record.get("researcher", [])
178             if (cred_object_hrn in researchers):
179                 rl.add("refresh")
180                 rl.add("embed")
181                 rl.add("bind")
182                 rl.add("control")
183                 rl.add("info")
184
185         elif type == "authority":
186             pis = record.get("pi", [])
187             operators = record.get("operator", [])
188             rl.add("authority,sa,ma")
189             if (cred_object_hrn in pis):
190                 rl.add("sa")
191             if (cred_object_hrn in operators):
192                 rl.add("ma")
193
194         elif type == "user":
195             rl.add("refresh")
196             rl.add("resolve")
197             rl.add("info")
198
199         return rl
200
201     def verify_cancreate_credential(self, src_cred, record):
202         """
203         Verify that a user can retrive a particular type of credential.
204         For slices, the user must be on the researcher list. For SA and
205         MA the user must be on the pi and operator lists respectively
206         """
207
208         type = record.get_type()
209         cred_object_hrn = src_cred.get_gid_object().get_hrn()
210         if cred_object_hrn in [self.config.GENI_REGISTRY_ROOT_AUTH]:
211             return
212         if type=="slice":
213             researchers = record.get("researcher", [])
214             if not (cred_object_hrn in researchers):
215                 raise PermissionError(cred_object_hrn + " is not in researcher list for " + record.get_name())
216         elif type == "sa":
217             pis = record.get("pi", [])
218             if not (cred_object_hrn in pis):
219                 raise PermissionError(cred_object_hrn + " is not in pi list for " + record.get_name())
220         elif type == "ma":
221             operators = record.get("operator", [])
222             if not (cred_object_hrn in operators):
223                 raise PermissionError(cred_object_hrn + " is not in operator list for " + record.get_name())
224
225     def get_authority(self, hrn):
226         return get_authority(hrn)